Summary: The Law of Demeter is discussed using Java source code examples.
Whenever you talk to a good, experienced programmer, they will tell you that “loosely coupled” classes are important to good software design. The Law of Demeter for functions (or methods, in Java) attempts to minimize coupling between classes in any program. In short, the intent of this “law” is to prevent you from reaching into an object to gain access to a third object’s methods.
The Law of Demeter is often described this way:
“Only talk to your immediate friends.”
or, put another way:
“Don't talk to strangers.”
A “Law of Demeter” Java example
Before getting into the theory, I think the Law of Demeter is best explained through a source code example, in this case, a Java example. Here then is a Java class which attempts to demonstrate what method calls are considered "okay" according to the Law of Demeter:
/** * A Law of Demeter example in Java. * Created by Alvin Alexander, http://alvinalexander.com. * This is an adaptation of the source code example from the book * The Pragmatic Programmer. */ public class LawOfDemeterInJava { private Topping cheeseTopping; /** * Good examples of following the Law of Demeter. */ public void goodExamples(Pizza pizza) { Foo foo = new Foo(); // (1) it's okay to call our own methods doSomething(); // (2) it's okay to call methods on objects passed in to our method int price = pizza.getPrice(); // (3) it's okay to call methods on any objects we create cheeseTopping = new CheeseTopping(); float weight = cheeseTopping.getWeightUsed(); // (4) any directly held component objects foo.doBar(); } private void doSomething() { // do something here ... } }
Now that you’ve seen the Law of Demeter in a Java example, here are the more formal rules for this law, as shown on the Wikipedia page:
The Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:
- O itself
- M’s parameters
- Any objects created/instantiated within M
- O’s direct component objects
- A global variable, accessible by O, in the scope of M
The Law of Demeter - Bad examples
Just as it’s helpful to see good examples of what you should do, it can also be helpful to see examples of what you shouldn’t do in your code. Let’s take a look at some “bad examples” of the Law of Demeter in Java.
In short, the Law of Demeter aims to keep you from doing things like this:
objectA.getObjectB().doSomething();
or even worse, this:
objectA.getObjectB().getObjectC().doSomething();
When you write code like this, not only are you exposing yourself to changes in the ObjectA class, you’re also exposing yourself to changes that may occur in ObjectB and ObjectC as well. Here are just a few ways these calls make your class more fragile:
- In the future, the class ObjectA may no longer need to carry a reference to ObjectB.
- In the future, the class ObjectB may no longer need to carry a reference to ObjectC.
- The doSomething() method in the ObjectB class may go away, or change.
- The doSomething() method in the ObjectC class may go away, or change.
- If the intent of your class is to be reusable, you can never reuse your class without also requiring ObjectA, ObjectB, and ObjectC to be shipped with your class. (This is referred to as "tight coupling", and you'll also hear the term "unnecessary dependencies".)
Forces
The Law of Demeter is a good practice to follow, and has the following positive benefits on the classes you create:
- Your classes will be “loosely coupled”; your dependencies are reduced.
- Reusing your classes will be easier.
- Your classes are less subject to changes in other classes.
- Your code will be easier to test.
- Classes designed this way have been proven to have fewer errors.
Consequences
While there are many good qualities about the Law of Demeter, there are consequences to following this “law” as well:
- If you truly need the doSomething() method of ObjectC, there are several possible solutions. The most clear solution is to require that ObjectC be passed in to your Java method.
- A second solution is to create wrapper methods in your other classes, and this wrapper methods will simply pass your request on to a delegate. In this case, a large number of delegate methods can make your code larger and slower (albeit more portable and easier to maintain).
Law of Demeter Java examples
I hope these Law of Demeter Java examples have been helpful. If you have any questions or comments, just leave a note in the Comments section below.