Law Of Demeter

The Law of Demeter (LoD) in a design principle, presented in Northeastern University at the end of 1987. The LoD aims to reduce coupling between classes, it says, “a module should not know about the innards of the objects it manipulates” (Robert C. Martin, The Clean Coder). The philosophy around LoD, is avoid getting deep in objects details and inner’s structure so we scale down the dependencies level.

The LoD projection on Object-oriented Programming, says if we have a class C and a function f, then f can only call the functions of:

  • f parameters.
  • object created by f.
  • functions of C.
  • functions of object of C.

To have a better understand of LoD, let’s use an example. Consider a simple piece of software to manage employee’s vacation request. Every employee have vacations counter, when he gets a day off the counter decrement and depends on his performance his boss’s increment the counter. So let’s define the code that let our employee get his Christmas vacation.

First the Employee class, an employee have a first name, a last name and a vacation counter.

public Class Employee {
  private String firstName;
  private String lastName;
  private Vacation vacation;

  public Employee(String firstName, String lastName, Vacation vacation){
       this.firstName = firstName;
       this.lastName = lastName;
       this.vacation = vacation;
  }

  public String getFirstName(){
       return firstName;
  } 

  public String getLastName(){
       return lastName;
  }

  public Vacation getVacation(){
       return vacation;
  }
}

Next the Vacation class that manage the vacation counter:

public Class Vacation {
  private int daysOffCounter;

  public Vacation(int counter){
       this.daysOffCounter= counter;
  }

  public int getVacation(int duration){
       daysOffCounter-= duration;
  }

  public void addVacation(int duration){
       daysOffCounter+= duration;
  }

  public int getDaysOffCounter(){
       return daysOffCounter;
  }
}

Now, let’s imagine the code that runs the boss to process a vacation request:

public void processVacation(Employee employee, int vacationDuration, boolean decesion){
     Vacation vacation = employee.getVacation();
     if(vacation.getDaysOffCounter() >= vacationDuration && decesion)
         vacation.getVacation(vacationDuration);
     else
	 // alert that the user have right to a vacation
     ...
}

In the code presented above we can easily notice a LoD violation because we have called the functions getOffDaysCounter() and getVacation(vacationDuration) of the vacation object, which is not permitted by the LoD (because vacation is an object returned by a function call).

What should we worry about ?

  • The processVacation function have one subject, which is the employee, but as we can see that she manipulates two objects the employee and vacation. So the class that contains this function depends on two classes (the Employee and Vacation classes) instead of one (Employee).
  • In the case of bad code, the function getVacation of the employee object can return null, so calling vacation.getVacation will throw a nullpointerexception.
  • Imagine if the boss asked to change the vacation request process, obviously the modifications are gone affect the concerned classes (employee, vacation) and the boss’s class.

How can we fix this code?

As I’ve mentioned earlier, LoD tells that a function don’t have to know about the inners of the object that she manipulates. In our case the employee is the subject and he is the one asking for a vacation, the only object she needs to manipulate is the employee. Therefore, the Employee class should encapsulate the vacation request submission process and the Vacation class should encapsulate the validation code. Let’s fix our code to suit up the LoD.

First the vacacation class, we update the getVacation method as follow:

public int getVacation(int duration) throws InvalidVacationRequest {
     if (daysOffCounter >= duration)
           daysOffCounter-= duration;
     else
        throw  new InvalidVacationRequest();
}

Then the submitVacation method of the employee class:

public void submitVacation(int vacationDuration, boolean decision) throws InvalidVacationRequest{
     if(decision)
       vacation.getVacation(vacationDuration);
     ...
}

Finaly, we update the boss’s confirmation code, as follow:

public void processVacation(Employee employee, int vacationDuration, boolean decesion){
     try {
       employee.submitVacation (duration, decesion);
       ...
     }catch (InvalidVacationRequest e){
       // alert the user that he doesn't have the right to get a vacation
     }
}

Why LoD is great?

  • LoD helps to scale down the dependencies level, the first version of processVacation depends on Employee’s and Vacation’s classes. By applying the Law of Demeter, the dependencies scale down to just the Employee’s classes.
  • LoD helps to write a clean code. In the example, we can easily notice that our code is much more readable and maintainable.

Train Wreck

A comment case of LoD violation is when a series of methods calls are appended to each other’s in one line, this is called Train Wreck. This styling code leads to readability and maintainability issues.

Example:

employee.getPayments().getLastPayment().add(YEAR_END_BONUSES);

This code is hard to read because it’s goes through a long series of methods and fetch through multiple objects and disciplines. Even worse, in the case of a bad code, if one of the functions fails down then all the chain will fail.

How LoD treat this case, it says that it’s unreasonable to fetch into objects inners so in the above train wreck we don’t have the right to fetch through to employee object. The solution is to encapsulate this line logic into a function of the employee object, this way consumer don’t have to access inners of the employee object:

employee.withdrowYearEndBonuses(YEAR_END_BONUSES);

Leave a comment