DEV Community

Walter Nascimento
Walter Nascimento

Posted on

Dependency Inversion Principle (DIP)

The Dependency Inversion Principle (DIP) is one of the SOLID principles that states that high-level modules should not depend on low-level modules. Both must depend on abstractions. In other words, high-level classes should not directly depend on low-level classes; both must depend on interfaces or abstractions, ensuring greater flexibility and code reuse.

Example Before Applying DIP in PHP:

Suppose we are developing an e-commerce system. We have an Order class that is responsible for processing orders and notifying customers about the order status. However, the Order class has a direct dependency on the EmailNotifier class, which is used to send confirmation emails to customers.

<?php

class EmailNotifier
{
    public function sendEmail($recipient, $message)
    {
        // Logic for sending a confirmation email
    }
}

class Order
{
    private $notifier;

    public function __construct()
    {
        $this->notifier = new EmailNotifier();
    }

    public function processOrder($customer, $message)
    {
        // Logic to process the order

        // Send confirmation email
        $this->notifier->sendEmail($client, $message);
    }
}

// Using the Order class
$order = new Order();
$order->processOrder('cliente@example.com', 'Your order was received successfully.');

Enter fullscreen mode Exit fullscreen mode

In this example, the Order class is directly coupled to the EmailNotifier class. This means that if we decide to use a different method to notify customers, for example via SMS or push notification, we would have to modify the Order class. This violates the principle of Dependency Inversion, as the high-level class (Order) is directly dependent on a low-level class (EmailNotifier).

Example After Applying DIP in PHP:

After applying the DIP, we will create a Notifier interface that represents any type of notifier, and then the Order class will depend on this interface instead of directly depending on a concrete implementation.

<?php

interface Notifier
{
    public function send($recipient, $message);
}

class EmailNotifier implements Notifier
{
    public function send($recipient, $message)
    {
        // Logic for sending a confirmation email
    }
}

class SMSNotifier implements Notifier
{
    public function send($recipient, $message)
    {
        // logic for sending SMS
    }
}

class Order
{
    private $notifier;

    public function __construct(Notifier $notifier)
    {
        $this->notifier = $notifier;
    }

    public function processOrder($customer, $message)
    {
        // Logic to process the order

        // Send notification using injected notifier
        $this->notifier->send($client, $message);
    }
}

// Using the Request class with Dependency Injection
$emailNotifier = new EmailNotifier();
$order = new Order($emailNotifier);
$order->processOrder('cliente@example.com', 'Your order was received successfully.');

Enter fullscreen mode Exit fullscreen mode

In this example, the Order class now depends on the Notifier interface, rather than a concrete implementation. This allows the Order class to be flexible and independent of the specific notifier implementation. If we need to change the notification type in the future, we can simply create a new class that implements the Notifier interface and inject it into the Order class without modifying the internal logic of the Order class. This way, the code follows the principle of Dependency Inversion, making it more flexible and easier to maintain.


Thanks for reading!

If you have any questions, complaints or tips, you can leave them here in the comments. I will be happy to answer!

😊😊 See you later! 😊😊


Support Me

Youtube - WalterNascimentoBarroso
Github - WalterNascimentoBarroso
Codepen - WalterNascimentoBarroso

Top comments (0)