Clean code
  • Overview
    • Introduction
    • Why is clean code so important?
    • What Is Clean Code?
    • How to write clean code?
    • Conventions
  • The key principles of clean code
    • Meaningful Names
    • Functions
    • Classes
    • Comments
    • Error Handling
      • Exception handling best practices
    • Unit Tests
    • Formatting
    • Objects and Data Structures
    • Simple Design Rules
    • Concurrency
    • Code Smells
  • Building Maintainable Software
    • Write Short Units of Code
    • Write Simple Units of Code
    • Write Code Once
    • Keep Unit Interfaces Small
    • Write Clean Code
    • Automate Tests
  • Bonus
    • SOLID Principle
      • SRP - Single Responsibility Principle
      • OCP - Open-Closed Principle
      • LSP - Liskov Substitution Principle
      • ISP - Interface Segregation Principle
      • DIP - Dependency Inversion Principle
    • LoD Principle
    • YAGNI Principle
    • DRY Principle
    • Fail Fast principle
    • Hollywood Principle
    • Library vs Framework
    • Coupling and Cohesion
    • AOP - Aspect-Oriented Programming
      • Building an AOP framework
    • OOP Design Pattern
    • Technical Dept
    • How to learn software Design and Architecture - Roadmap
    • Microservcies
      • Defining the scope of a microservice
      • Step-by-Step: How to Identify Over-Scoped Microservices
      • Benefits of Grouping or Consolidating Microservices
      • A practical step-by-step plan to consolidate microservice
Powered by GitBook
On this page
  • LoD Rules
  • Examples
  1. Bonus

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.

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

public class UserService {

    private UserRepository userRepository;

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

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

    private void sort(List<User> users, String direction) {}
}

Examples

Example 1:

private OrderService orderService;

public void getOrderDetail() {
    Oder order = orderService.getOrder();
    Customer customer = orderService.getCustomerService().getCustomer(customerId); // Violate LoD
}
private OrderService orderService;
private CustomerService customerService;

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

Example 2:

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
    }
}

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

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();
    }
}
PreviousDIP - Dependency Inversion PrincipleNextYAGNI Principle

Last updated 2 years ago