The Law of Demeter

27 Jul 2014

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 of foo)

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.

Hi, I’m Nithin Bekal.
I work at Shopify in Ottawa, Canada.
Previously, co-founder of
CrowdStudio.in and
WowMakers.
Ruby is my preferred programming language,
and the topic of most of my articles here,
but I'm also a big fan of Elixir.
Tweet to me at @nithinbekal.