Scoping refers to how software programs control which parts of the system can see which other parts. Back in the day, most things were global which meant that everything could see (and touch) everything else. This made writing the code easy, until you had a variable suddendly change out from under you. You then got to spend long hours finguring out who might have changed it...and you had to look everywhere because everyone had access.
Programming languages such as Java provide a number of scopes that can be specified to control who can see a particular variable. Ask the average Java programmer how many types of scope there are and they'll probably say three: public, private and protected. Public scope is like the old global...a public object can be seen and touched by anyone. Private scope is basically the opposite...a private object can only been seen by the class that owns it. Conventional wisdom says that most things should be private. Protected scope is a variation on private. A protected variable can be seen the class that owns it or by any class derived from that class.
Thats the answer you'll get from the average programmer, but its the wrong answer.
The right answer is that there are four scopes in Java. The scope that most people forget about is package scope. An object with package scope can be seen by any other object in the package. This is a surprisingly useful scope and so its a bit surprising that so many programmers ignore it. Part of the reason for that is that while the other three scopes each have keywords, you get package scope by not specifying any scope. Personally I think the language should have included a package_scope keyword so as to make this clear but thats water under the bridge.
Why is package scope so interesting?
Consider a software system with two classes: One and Two. Assume that we want to expose two methods to the outside world "begin()" and "end()". Further assume that each class needed to call a method in the other class. The following is the sort of code that most people would write.
package sample;
public class One {
public begin() {
new Two().internal();
}
public internal1() {
}
}
package sample;
public class Two {
public end() {
new One().internal1();
}
public internal2() {
}
}
Most people would tend to make the two internal methods public so that the two classes could use them. The problem with that is that it makes the two internal methods part of the publically accessible API of the overall system. A user of this package has no particular clue that they should or should not call those internal methods.
A better approach is to remove the "public" in the declaration of the two internal methods. This leaves them at package scope, which is just fine. The two classes are in the same package and so have access to all package scope methods. The two internal methods are now however absent from the publically visible API of the system, which is as it should be.
So, the rule of thumb should be:
default to making classes and methods package scope
make methods only used within a class private
and, only grudgingly make the hopefully small number of truely public methods be declared as public.
Your users and maintainers will thank you.
Let's not forget how much easier testing becomes thanks to package scope.
ReplyDelete