By now, most programmers are familiar with the law of demeter. I think there’s still a great deal of misunderstanding of what it means and how to use it. It’s often tersely explained as a call chain with two dots, but the “two dots” rule is merely a heuristic for identifying possible demeter violations. Seeing a call chain with two dots doesn’t necessarily mean demeter is being violated. To understand why, you have to go beyond that simple explanation and think about what it means and why it matters.
In following the law of demeter, our goal is to write encapsulated code. In writing encapsulated code, our goal is to expose an object’s behavior while hiding its internal structure. The key thing to understand is that if your object doesn’t have behavior, and you’re primarily interested in the structure, then the law of demeter doesn’t apply. Let’s look at an example.
Say you’re writing an application that simulates an auto race. You’ve got a car domain object, and it has some components to it. A race track object tells the cars when to start their engines.
In this case, you absolutely benefit by applying the law of demeter. Let’s say down the road there’s more work that needs to be done when starting the engine, such as charging a turbofan (I have no clue if that makes sense. I don’t know anything about car racing). If you violate demeter, which looks like
you see that you have to change the Race class. First off, that’s odd, as you would expect changes to a Car’s behavior to be made in Car’s definition, not Race. Secondly, you’re guaranteeing bugs somewhere down the road, because when you have a different object start a car’s engine, you have to maintain this in two spots. If you don’t think you’ll ever have another object that tells a car to start its engine, consider your tests and think again.
Following demeter is valuable when you have behavioral objects. In the previous example, a Race deals with a Car abstraction, but doesn’t care anything about the Car’s engine. An engine is an internal object that helps the Car do something interesting.
When you care about structure, expose structure
Let’s look at another example, in this case it’s going to be a Rails app that lets you build a car, selecting the options that you want. The confirmation page looks something like
There’s no behavior, it’s all structure. And in this case, structure is what we care about. Because of this, following demeter would only result in needless indirection and code without providing any benefits.
The law of demeter is a useful guideline, but as with any other programming guideline you need to understand its subtleties in order to use it effectively. Demeter should be used as an encapsulation technique, when you want a behavioral object that hides its structural details. When you’re interested in an object’s structure, you’re better off leaving demeter in your toolbox.