Dependency Inversion Principle (DIP)
Walter Nascimento
Posted on November 7, 2023
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.');
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.');
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
Posted on November 7, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.