# LoD Principle

**The Law of Demeter (LoD) or principle of least knowledge says a module should not know about the internals of the objects it manipulates.**&#x20;

An object should not expose its internal structure through accessors because to do so is to expose, rather than to hide, its internal structure.

The advantage of following the Law of Demeter is that the resulting software tends to be more maintainable and adaptable. Since objects are less dependent on the internal structure of other objects, object containers can be changed without reworking their callers.

## LoD Rules

The Law of Demeter says that a method _**f**_ of a class _**C**_ should only call the methods of these:

1. _C_
2. An object created by _f_
3. An object held in an instance variable of _C_
4. An object passed as an argument to _f_

{% hint style="success" %}
<pre class="language-java"><code class="lang-java"><strong>public class UserService {
</strong>
    private UserRepository userRepository;

    public List&#x3C;User> getUsers(UserFilter filter) {
        QueryBuilder queryBuilder = new QueryBuilder();
        Query query = queryBuilder.build(filter); // rule 2

        List&#x3C;User> users = userRepository.getUsers(query); // rule 3
        
        String direction = filter.getSort(); // rule 4
        
        this.sort(users, direction); // rule 1
    }

    private void sort(List&#x3C;User> users, String direction) {}
}
</code></pre>
{% endhint %}

## Examples

**Example 1:**

{% hint style="danger" %}
<pre class="language-java"><code class="lang-java"><strong>private OrderService orderService;
</strong>
public void getOrderDetail() {
    Oder order = orderService.getOrder();
    Customer customer = orderService.getCustomerService().getCustomer(customerId); // Violate LoD
}
</code></pre>
{% endhint %}

{% hint style="success" %}
```java
private OrderService orderService;
private CustomerService customerService;

public void getOrderDetail() {
    Oder order = orderService.getOrder();
    Customer customer = customerService.getCustomer(customerId);
}
```
{% endhint %}

**Example 2:**

{% hint style="danger" %}
```java
class Company {

    private List<Department> departments;

    Map<DepartmentCode, BigDecimal> costPerDepartment() {
        return departments.stream()
                          .filter(this::costCenter)
                          .collect(Collectors.toMap(Department::getCode, Department::cost));
    }

    private boolean costCentre(Department department) {
        return department.getType() instanceof CostCentre; // Violate LoD
    }
}
```
{% endhint %}

Instead of digging in Department details, it is better to ask, if a department is a cost centre.

{% hint style="success" %}
```java
class Company {

    private List<Department> departments;

    Map<DepartmentCode, BigDecimal> costPerDepartment() {
        return departments.stream()
                          .filter(this::costCentre)
                          .collect(Collectors.toMap(Department::getCode, Department::cost));
    }

    private boolean costCentre(Department department) {
        return department.isCostCentre();
    }
}
```
{% endhint %}
