OOD Principles and Rails: The Law of Demeter


Understanding the Law of Demeter

The Law of Demeter (LoD) or principle of least knowledge advocates for minimal knowledge of a component about other components.

In Rails, it’s tempting to chain method calls due to ActiveRecord associations.

Frequent utilization, such as <%= @invoice.customer.name %>, increases coupling and potential maintenance woes.

Code Smells: Chain Dependencies

Chaining dependencies, e.g., <%= @invoice.customer.address.city %>, poses serious risks:

  • Increased Dependency: Any change in model structure demands modifications across multiple files, elevating maintenance costs.
  • Breaking Encapsulation: It exposes internal details of the object’s relationships, making refactoring and testing challenging.

Refactoring to Improve: Delegation vs Direct Method Calls

Refactoring <%= @invoice.customer.name %> to <%= @invoice.customer_name %> helps adhere to LoD, reducing the system’s brittleness. Here’s why direct method calls can be harmful:

# Bad: High coupling and encapsulation breach
<%= @invoice.customer.name %>

Switching to:

# Good: Reduced coupling and encapsulation preserved
class Invoice < ActiveRecord::Base
  def customer_name
    customer.name
  end
end

We shift responsibility, enhancing cohesion within the Invoice class, simplifying code, and easing refactoring.

Practical Implementation in Rails: Using delegate

Rails offers a succinct solution using delegate for better maintainability and adherence to LoD.

Here’s what the evolution looks like:

# Before: Manual method definitions
class Invoice < ActiveRecord::Base
  def customer_name
    customer.name
  end
end

Refactor with delegate:

# After: Elegant delegation
class Invoice < ActiveRecord::Base
  delegate :name, :street, :city, :state, :zip_code, to: :customer, prefix: true
end

This refactoring ensures:

  1. Clear Declarations: The delegate keyword clearly states where the forwarded messages are sent, improving readability and traceability.
  2. Simplification: Reduces the clutter of manual getter methods in the model.
  3. Adherence to LoD: Code remains compliant with LoD by using single-level interaction.

In view templates, usage stays succinct and maintenance-friendly:

<%= @invoice.customer_name %>
<%= @invoice.customer_street %>

Following the Law of Demeter in Ruby on Rails using delegate not only upholds OOP principles but also ensures cleaner, more reliable code, adjustable with lesser effort to future changes.


Related posts

Free Training By Email:
Building a Rails Engine

We will send udpates but we care about your data.
No spams.

Back to homepage