The Law of Demeter

The Law of Demeter (principle of least knowledge) is a design guideline which was first discussed in 1987 by Ian Holland at Northeastern University.

“For all classes C, and for all methods M attached to C, all objects to which M sends a message must be instances of classes associated with the following classes:

  1. The argument classes of M (including C).
  2. The instance variable classes of C.

(Objects created by M, or by functions or methods which M calls, and objects in global variables are considered as arguments of M). ”

With regards to object-oriented programming it can be described as the following:

A method of an object may only call methods of:

  1. The object itself.
  2. An argument of the method.
  3. Any object created within the method.
  4. Any direct properties/fields of the object

Example:

The models used in the following example is that of a blogger, post and destination. A blogger and destination both have many posts. Therefore a blogger has many destinations through posts.

Blogger -< Post >- Destination

Say we want the country a blogger last posted about, the method would look like the following:

blogger.posts.last.destination.country

This kind of code is often called a train wreck because it looks like a bunch of coupled train cars. Chain calls such as this are considered to be a sloppy style and are generally avoided, violating the Law of Demeter.

Firstly we’d have to write the following method in the Blogger class:

class Blogger < ApplicationRecord
has_many :posts
has_many :destinations, through: :post
def last_post
posts.last
end
end

The original method would be reduced to:

blogger.last_post.destination.country

This can further be reduced with the use of delegation. Delegation provides a delegate class method to easily expose contained objects’ public methods as your own. In other words they take some methods and send them off to another object to be processed.

Note on syntax:

  • :to — Specifies the target object
  • :prefix — Prefixes the new method with the target name or a custom prefix
  • :allow_nil — if set to true, prevents a NoMethodError to be raised
class Post < ApplicationRecord
belongs_to :blogger
belongs_to :destination
delegate :country, to: :destination, prefix: true, allow_nil: true

end

Now we have the ability to call:

blogger.last_post.destination_country

However, the code still smells a bit so a further method needs to be written.

class Blogger < ApplicationRecord
has_many :posts
has_many :destinations, through: :post
def last_post
posts.last
end
def country_of_last_post
last_post.destination_country
end
end

Finally we are able to call on the country a blogger last posted about using a single dot.

blogger.country_of_last_post

We now don’t break the Law of Demeter as we are able to access the country directly from the blogger model, shown by the use of a single dot. Hence the Law of Demeter commonly being referred to as the one dot rule.

Fundamentally the goal of the Law of Demeter is to produce objects that are loosely coupled.

Tightly coupled objects are highly dependent on each other and require a great deal of information about each other for methods to function.

Loosely coupled objects have a minimum number of dependencies and know little about the methods of other classes.

Advantages and Disadvantages:

Advantages

  • Increased readability/cohesion thus increasing maintainability and adaptability as result of minimising the number of changes that must be made when aspects of the code are altered.
  • Reduces risk of unrevised methods going unnoticed somewhere else in the code.
  • If objects are too tightly coupled and the order in which methods receive arguments is altered, the arguments must be switched everywhere else the method is called within the code.

Disadvantages

  • Requires a large number of wrapper methods to carry information between distant objects, since the information can’t otherwise be retrieved.

Thanks for reading! Hope you found this blog useful.