Introduction

Welcome to the third lesson of the "Applying Clean Code Principles" course. In our journey so far, we've discussed the importance of the DRY (Don't Repeat Yourself) principle for eliminating redundancy in code. We followed that with the KISS (Keep It Simple, Stupid) principle, which highlights the value of simplicity in software development. Today, our focus is on the Law of Demeter — a key guideline in structured programming. By limiting the knowledge that an object has about other objects, this lesson will guide you in crafting more maintainable and modular code.

Understanding the Law of Demeter

The Law of Demeter suggests that an object should only communicate with its immediate collaborators, avoiding the entire system. By reducing dependency between parts, you'll find your code easier to maintain and scale. In simple terms, a method X of the class C should only call the methods of:

  • Class C itself
  • An object created by X
  • An object passed as an argument to X
  • An object held in an instance variable of C
  • A static field

With these principles, you control how parts of your application interact, leading to a more organized structure. Let's explore how this works with examples. 🚀

First Rule Example

For the first point, a method should only access its own class's methods:

class Car {
    public function start(): void {
        $this->checkFuel();
        $this->ignite();
    }
    
    private function checkFuel(): void {
        echo "Checking fuel level...\n";
    }
    
    private function ignite(): void {
        echo "Igniting the engine...\n";
    }
}

In this example, the start method interacts solely with methods within the Car class itself. This shows how you maintain clear boundaries adhering to the Law of Demeter.

Second Rule Example
Third Rule Example

Continuing, let's look at interacting with objects passed as arguments:

class Printer {
    public function print(Document $document): void {
        $document->sendToPrinter();
    }
}

class Document {
    public function sendToPrinter(): void {
        echo "Document is being printed...\n";
    }
}

The Printer class method print communicates with the Document object passed as an argument, aligning with the Law of Demeter by limiting communication to direct method parameters. 🖨️

Fourth Rule Example

Objects held in instance variables of a class can also be accessed:

class House {
    private Door $door;
    
    public function __construct() {
        $this->door = new Door();
    }
    
    public function lockHouse(): void {
        $this->door->close();
    }
}

class Door {
    public function close(): void {
        echo "Door is closed.\n";
    }
}

In this example, the House class interacts with its door through the lockHouse method, showcasing compliance by interacting with an object it holds in an instance variable. 🏠

Fifth Rule Example

Finally, let's see a method interacting with static fields. While static fields are convenient, they should generally be used cautiously since they can lead to shared state issues in larger applications:

class TemperatureConverter {
    private const CONVERSION_FACTOR = 9.0 / 5.0;
    
    public function celsiusToFahrenheit(float $celsius): string {
        return (int)(($celsius * self::CONVERSION_FACTOR) + 32);
    }
}

Here, CONVERSION_FACTOR is defined as a const to indicate that it's a constant, and to ensure correct calculations, the division is a float. Accessing static fields like this is compliant with the Law of Demeter. 🌡️

Violation Example
Refactored Example
Summary and Next Steps

The Law of Demeter plays a vital role in writing clean, modular code by ensuring objects only interact with their closest dependencies. By understanding and implementing these guidelines, you enhance the modularity and maintainability of your code. As you move on to the practice exercises, challenge yourself to apply these principles and evaluate your code's interactions. Keep these lessons in mind as essential steps toward mastering clean code! 🌟

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal