97TESPK: Scoping Methods

Posted by Michael Hunger on Mar 5, 2010 in 97TESPK, code, patterns, writing |
97 things every programmer should know on compass table

Now that 97 things every programmer should know lies on my compass table, I’ll post my contributions here that didn’t make it into the book.

The first is “scoping methods” which I thought about while reading Uncle Bob Martin’s Clean Code. He discussed scoping variables but only about putting methods near to each other. Obviously there was a missing piece. I tried to write it down.

It has long been recommended that we should scope our variables as narrowly as possible. Why is that so?
Readability is greatly improved if the scope of a named variable is so small that you can see its declaration only a few lines above its usage.

Variables leaving scope are quickly reclaimed from the stack or collected by the garbage collector.
Invalid reuse of locally scoped variables is impossible.

Singular assignment on declaration encourages a functional style and reduces the mental overhead of keeping track of multiple assignments in different contexts

Local variables are not shared state and are therefore automatically thread safe.

But what about scoping our methods?

We try to decompose methods into smaller units of computation, each of which is easily understandable. This goes hand in hand with the principle that a method should deal only with a single level of abstraction. If the result, however, is that your class then houses too many small methods to be easily understandable, it’s time to rescope its methods. Although similar in some ways, that’s not quite the same as decomposing classes with low cohesion into different smaller classes. The class may be quite cohesive, it’s just that is spans too many levels of abstraction.

Although there are layout rules that make locality and access more significant (like putting a private method just below the first method that uses it), scoping is a cleaner way of separating cohesive parts of a class.

How do you scope methods?

Create objects that correspond to the public methods, and move the related private methods over to the method objects. If you had parameter lists for the private methods — especially long ones — you can promote these some of these parameters to instance variables of the method object.

You then have your original class declare its dependencies on these fragments and orchestrate their invocation. This keeps your original class in a coordinating role, freed from the detail of private methods. The lifetime of your method objects depends on their intended use. Mostly I create them within the scope just before being called and let them die immediately after. You may also choose to give them more significant status and have them passed in from outside the object or created by a factory.
These method objects give the newly created method scope a name and a location. They stay very narrowly focused and at a consistent level of abstraction. Often they become home for more functionality working on the state they took with them, e.g., the promoted parameters or the instance variables used by just these methods.

If you have private methods that are often reused within different other methods it’s perhaps time to accept their importance and promote them to public methods in a separate method object.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • LinkedIn
  • Netvibes
  • PDF
  • Ping.fm

Tags: , , ,

1 Comment

  • Jens Nerche says:

    Hi Michael,
    it seems your discussion misses some details. Let me play devils advocate and to formulate some protest notes:

    Scoping Methods lead to anemic domain models. Because one logical class is spread over some physical classes, each containing some methods, there is no hidden information with public operations on it anymore just like in service-dto-dao-architectures. The former private methods, which operate on the class data, now need dto’s for input and output, no real internal hidden state anymore.

    Not only the data isn’t protected anymore, there is also no private method anymore. Things may become visible to far more objects than they should, and it unsafer to change things.

    In the same namespace are now far more classes than before, which leads to fat namespaces (packages). And because the lack of any naming convention its not obvious which code belongs together. Before scoping the cohesive code was in one class, now its spread over all the namespace.

    The code is now much less readable, now you have to switch between files instead of having it on one screen or scroll some pages up and down. There is also much more syntactic sugar to write and read.

    “Transit dependencies” are common: that are dependencies that are injected in the original class – not for the own use, but only to pass them to the newly created method objects (which in turn may pass them only to their method objects and so on…)

    There is no real point for having method objects – static utility methods could also do the job. They could be imported statically and are in the original class as readable as private methods. And its a heaven for utility methods collection classes. We could also define abstraction levels 1-10 and have a utility method class per abstraction level just as we could have a database table per data type and spread the entity over them ;-> Well, not really….

    Perhaps the object oriented paradigm is the wrong one for the abstraction hierarchies you are seeking for. In the described form Scoping Methods is more one of the “97 Bad Ideas Every Programmer Should Know”.

    Don’t get me wrong, I’m not trying to bash you or so, I’m just playing the devil to point out some antitheses.

    live long and prosper
    jens

Leave a Reply

XHTML: You can use these tags:' <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Copyright © 2007-2010 Better Software Development All rights reserved.
Multi v1.4.5 a child of the Desk Mess Mirrored v1.4.6 theme from BuyNowShop.com.