How To Implement Law Of Demeter In Ruby

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 :\ Wikipedia: 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.

You might also enjoy reading: Template Method Design Pattern in Rails

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.

Final Words

Ruby is a dynamic, high-level, general-purpose programming language known for its simplicity and productivity. Explore our awesome projects on Ruby .

Need a team of expert Ruby developers for your next big project? Hire the best team of developers from Gurzu. Book a free consultation call with us today to learn more!