Java Reference
In-Depth Information
By doing work in the constructor (other than populating instance variables), we mix
the first and second points in our list. It's a bad practice not only from architectural
point of view (we'll do the same work every time we instantiate our class) but also
because we always get our class in a predefined state. This code is hard to maintain
and test.
5.2.4
Follow the Principle of Least Knowledge
The Law of Demeter, or Principle of Least Knowledge, is a design guideline that states
that one class should know only as much as it needs to know. For example, consider
listing 5.3:
Listing 5.3
Law of Demeter violation
class
Car {
private
Driver driver;
Car(Context context) {
this
.driver = context.getDriver();
}
}
In this example, we pass to the
Car
constructor a
Context
object. This is a violation of
the Law of Demeter, because the
Car
class needs to know that the
Context
object has a
getDriver
method. If we want to test this constructor, we need to get hold of a valid
Context
object before calling the constructor. If the
Context
object has a lot of vari-
ables and methods, we could be forced to use mock objects (see chapter 7) to simu-
late the context.
The proper solution is to apply the Principle of Least Knowledge and pass refer-
ences to methods and constructors only when we need to do so. In our example, we
should pass the
Driver
to the
Car
constructor, as in the following:
Car(Driver driver) {
this
.driver = driver;
}
That illustrates a key concept:
Require objects, don't search for objects, and ask only for objects
that your application requires.
5.2.5
Avoid hidden dependencies and global state
Be careful with global state because global state makes it possible for many clients to
share the global object. This can have unintended consequences if the global object is
not coded for shared access or if clients expect exclusive access to the global object.
For instance, consider the example in listing 5.4.
Listing 5.4
Global state in action
public
void
reserve() {
DBManager manager = new DBManager();