Scoping Methods

From WikiContent

(Difference between revisions)
Jump to: navigation, search
(New page: == Method scopes == It has long been known that we should scope our variables as narrow as possible. And with the advent of modern compilers even more so as they move them into the best l...)
Current revision (03:14, 19 July 2009) (edit) (undo)
 
(5 intermediate revisions not shown.)
Line 1: Line 1:
-
== Method scopes ==
+
It has long been recommended that we should scope our variables as narrowly as possible. Why is that so?
-
It has long been known that we should scope our variables as narrow as possible. And with the advent of modern compilers even more so as they move them into the best location in the binary anyway. 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.
-
* Readability is greatly improved if the scope of a named variable is so small you can see its declaration some lines above its usage.
+
-
* Variables leaving scope are quickly collected by the Garbage Collector.
+
* Invalid reuse of locally scoped variables is impossible.
* Invalid reuse of locally scoped variables is impossible.
-
* ''Assign once strategy'' (final local variables) is much easier.
+
* 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 no shared state and therefore thread safe
+
* Local variables are not shared state and are therefore automatically thread safe.
-
* etc.
+
 
 +
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.
-
But what about methods?
+
How to scope methods?
-
Its commonly discussed that you should manage the visibility of your methods by making only that public what should be exposed by the public interface. Keep overrideable methods for subclasses abstract or empty. Sometimes there are some layouting rules like - first the public then the private methods. Or the one from Uncle Bob - put the private method near their first usage (just below the public method which uses it).
+
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.
-
Why don't we scope methods as well?
+
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.
-
It is easy and helps a lot with the Single Responsibility Principle (SRP) - have one reason to change a class - and One Level Of Abstraction - within a (method) scope only have invocations on the same level of abstraction, no nested structures.
+
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.
-
Just create objects for the public methods and move the private ones along with them. If you had (long) parameter lists for the private methods you can promote these parameters to instance variables of the method object.
+
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.
-
Then have your original class declare its dependencies on these fragments and orchestrate their invocation. This keeps your orchestrating class in a controlling role and free of lots of small (as we like it) 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 instantly die. You may also choose to give them higher status and have them injected by an DI framework or created by a factory.
+
By [[Michael Hunger]]
-
These Method Objects give the newly created method scope a name and a location. They stay very narrowly focused (SRP). Often they become home for more functionality working on the state the took with them (e.g. promoted parameters or instance variables used by just these methods.)
 
-
If you have private methods that are quite often reused within different other methods it's perhaps time to accept their importance and promote them to public methods in a Method Object (or utility class -> traditional function for non-functional languages)
+
This work is licensed under a
 +
[http://creativecommons.org/licenses/by/3.0/us/ Creative Commons Attribution 3]
-
Partially this is comparable with AOP but this approach makes the delegated functionality visible as these are no cross cutting (technical) concerns but business functionality. A much better discussion about this principle is done by Jim Coplien (DCI - data context interaction) and Rickard Öbergs (COP - composite oriented programming, available in the qi4j framework) which focus on composing objects out of many fragments depending on the current role of the object within the current execution context.
+
Back to [[97 Things Every Programmer Should Know]] home page

Current revision

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 to 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.

By Michael Hunger


This work is licensed under a Creative Commons Attribution 3

Back to 97 Things Every Programmer Should Know home page

Personal tools