The law of Demeter
Reducing the dependencies between classes is a good way to make your code more flexible. The Law of Demeter is a technique that helps with this and reduces coupling between objects. Let’s see how you can apply this to your Ruby code (but remember that these rules apply to any object oriented code).
The Law of Demeter states that when you call a method bar(x, y)
on an object foo
, it should only interact with objects that are closely related to it. The kinds of objects on which bar
can invoke methods are:
- the object
foo
itself (ie. any instance methods offoo
) - the arguments of the method
bar
(ie. x and y) - any objects instantiated inside the method
bar
- attributes (instance variables) of
foo
Here, calling x.foobar()
or @some_attr.foobar()
is OK, but x.baz.foobar()
and @some_attr.bar.foobar()
are not.
The Paperboy and Wallet Metaphor
The metaphor of a paper boy collecting money from a customer (described in this paper) is an excellent way to understand the Law of Demeter. Imagine a Paperboy
class that must collect money from a Customer
:
The Paperboy is relying on the knowledge that a customer has a wallet and that it has cash. What happens now if Wallet changes its interface and uses the name balance
instead of cash
? Or adds a bang (!
) to the #withdraw
method to indicate that it changes the state of the wallet?
To avoid this, we could make the Customer responsible for paying, while the Paperboy only knows that Customer has a #pay_amount
method.
Now the Paperboy
can simply call #pay_amount
on Customer
and not have to worry if the money is coming out of a wallet. The customer could be paying with the loose change in their pocket, without reaching for the wallet, and the paper boy doesn’t need to know about that detail.
This isolates the Paperboy
from any changes in Wallet
. If you were to change the internals of Wallet
, it would not have any effect on the other classes. Even if you were to change the interface to #withdraw
, the only change needed would be in Customer
.
Related articles
- The Paperboy, the Wallet and the Law of Demeter [PDF]
- Practical Object Oriented Design in Ruby: Interfaces, by Sandi Metz
- Demeter - It’s not just a good idea. It’s the law - article by Avdi Grimm