Law of Demeter

The Law of Demeter, also known as the Principle of Least Knowledge is a subtle but important factor in software design. It often points to deficiencies in the design of objects and how objects interact.

Only talk to your immediate friends.

Un-demetered code can sometimes surface as code that is procedural instead of object-oriented and lacks encapsulation. From the consumers perspective this results in increased Efferent Coupling to all the types exposed. Un-demetered code is inherently brittle because of the amount of types a consumer is exposed to when executing an operation. The consumer depending on so many types will break if any of those types change.

customer.InsurancePortfolio.Policies[policy].Pay(amount);

This example line of code violates the Law of Demeter. Any consumer calling the method to pay an amount against the balance of the policy is brittle because any number of things can change because the internal structure of the objects are exposed.

Frequently breaking tests when implementation details change is a good indication un-demetered (and tightly coupled) code may exist.

Reuse of un-demetered code becomes difficult because of increased coupling to internal structures of objects.

It’s not about counting the dots

The statement Only talk to your immediate friends can sometimes be misunderstood for dot counting on an operation.

Team team = new TeamBuilder().CreateTeam("New York Rangers")
    .WithNickName("Rangers")
    .WithShirtColor("Blue")
    .FromTown("New York")
    .PlayingAt("Madison Square Garden");

This usage of a fluent builder is an example where the Law of Demeter isn’t violated because it’s endomorphic. Similar to functional programming, all the chained method calls return the same type (TeamBuilder).

How to improve

Rethink your model (classes, responsibilities, processes, interaction patterns) but don’t just move the problem from one class to another. This may drive you towards creating multiple models because you may find different needs and that an all encompassing model increases coupling.

customerInsurancePolicy.Pay(amount);

One possibility is to create a class called CustomerInsurancePolicy that encapsulated both the required customer information and policy information so that you can reduce the coupling on the payment operation.

Domain Driven Design

In domain driven design there is the concept of an Aggregate Root which can be summarized from the website as:

A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the Aggregate, designated as the root. A set of consistency rules applies within the Aggregate’s boundaries.

In DDD, a well designed Aggregate Root follows the Law of Demeter.

public class Order
{
    public void UpdateSeats(
        IEnumerable<OrderItem> items,
        IPricingService pricingService) { }

    public void MarkAsReserved(
        IPricingService pricingService,
        DateTime expirationDate,
        IEnumerable<SeatQuantity> reservedSeats) { }

    public void Expire() { }
    public void Confirm() { }

    public void AssignRegistrant(
        string firstName,
        string lastName,
        string email) { }

    public SeatAssignments CreateSeatAssignments() { }
}

Here is an example of the Order Aggregate Root from the CQRS Journey project the Microsoft Patterns and Practices team is working on. I’ve left out the implementation details. Notice the lack of properties exposed. The lack of exposing internal structure reduces the coupling required by consumers.

In object-oriented programming this is often called Tell, don’t ask.

Advantages

Code tends to be more maintainable and adaptable. Since objects are less dependent on the internal structure of other objects, object internals can be changed without reworking their consumers. Lower Response For a Class (the number of methods potentially invoked in response to calling a method of that class) can reduce the probability of bugs. The Law of Demeter leads to narrow interfaces at the method level.

Disadvantages

The Law of Demeter leads to wider interfaces at the class level due to the introduction of more methods instead of navigating directly into the object structure. This increases Weighted Methods per Class (the number of methods defined in each class) and can increase the probability of software bugs.

Startups