How To Implement Law Of Demeter In Ruby

Engineering
Gurzu Engineer

Most of the developers who are digging deeper into proper way to build software might have had problem in understanding the law of Demeter in first go. Here is our attempt to simplify this for the new generation of developers.

You can read the formal definitions here :\ C2wiki: http://c2.com/cgi/wiki/LawOfDemeter?LawOfDemeterWikipedia: https://en.wikipedia.org/wiki/Law_of_Demeter

Law of Demeter

The law of Demeter fundamentally describes following things: 

  • Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.
  • Each unit should only talk to its friends; don’t talk to strangers.
  • Only talk to your immediate friends.

In our context as programmers, an object should avoid calling on methods of a member object returned by another method. For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as “use only one dot”. That is, the code a.b.Method() breaks the law where a.Method() does not.

Ruby on Rails Bad smell code:

class Project < ActiveRecord::Base\
  belongs_to :user\
end

project.user.name\
project.user.address\
project.user.cellphone

These lines break law of Demeter. To solve this we should use methods like as:

project.user_name\
project.user_address\
Project.user_cellphone

Now, this follows the law of Demeter. But if we use methods for each field then we need to add bunch of methods in the model.

class Project < ActiveRecord::Base\
  belongs_to :user\
  def user_name\
    user.name\
    end\
  def user_address\
    user.address\
  end\
  def user_cellphone\
    user.cellphone\
  end\
end

class User < ActiveRecord::Base\
  has_many :projects\
end

To remove above bad smell Rails provides a helper method delegate which utilizes the DSL way to generates the wrapper methods. This is the best practice.

delegate:

The concept of delegation is to take some methods and send them off to another object to be processed.

Options:

: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 Project < ActiveRecord::Base\
  belongs_to :user\
    delegate :name, :address, :cellphone, to: :user, prefix: true, allow_nil: true\
end

class User < ActiveRecord::Base\
  has_many :projects\
end

project.user_name

project.user_address

This is how the method can now be accessed with delegate enabled.

Now, we do not break the law of Demeter. Due to addition of allow_nil if the project  does not have any user then we will just get nil when calling name and no exception!

Now we know what the law of Demeter is . But why use it ?. Most of the blog posts out there does not answer this specific question. What are the benefits or advantages of implementing law of Demeter in our ruby software’s?

In general , Law of Demeter is an example of loose coupling which states that one component should not heavily rely on other components for getting the job done. \ Not when we decrease this coupling. Things are much much easier to change.

But what about the famous method chaining we are used to ?

But  If we followed it all the time we could never do method chaining

Method chains are what makes ruby well ruby !  As an example, here’s a method which takes a string and generates a “slug” for generating a friendly url:

def slug(string) 

  string.strip.downcase.tr_s('^\[a-z0-9]', '-‘) 

end

That’s three levels of method call chaining. That does not follow the Law of Demeter. But the law never says anything about the number of methods called, or the number of objects a method uses. It is strictly concerned with the number of types a method deals with.

The #slug method expects a String, and calls three methods, each one returning… another String. In fact, because it only calls methods for the type of object (String) passed into it as parameters, we can conclude that it follows  the Law of Demeter.

Share Article

Few more blogs...