Dependency Inversion Principle

"There are two parts to learning craftsmanship: knowledge and work." - Robert C. Martin

Dependency Inversion Principle

odwrócenia zależności

According to the Dependency Inversion Principle, all dependencies should depend on abstraction, not on a particular type. So a high-level class should not depend on a low-level class, but both classes should depend on abstraction. High level modules (classes) are most often responsible for important strategic decisions and models of a given application. Therefore, they are the most responsible for the functioning of the entire application. If high-level modules depended on low-level modules, changes to the low-level elements would also require changes to higher levels. In addition, when high-level modules depend on low-level ones, re-use is often difficult. Reversing this dependence in the other direction means that it can be used many times. Therefore, the source code should not depend on a particular class, such dependencies should end on abstract classes or interfaces. The code written in accordance with the DIP principle is much simpler to maintain. Below is the code written against the DIP principle.

 
class Plane 
{ 
} 

class Engine 
{ 
public function startEngine() 
{ 
echo 'Starting engine!'; 
} 
} 

class OnBoardComputer 
{ 
public function takeOff(Plane $plane) 
{ 
$start = new Engine(); 
$start -> startEngine($plane); 
} 
} 

$plane = new OnBoardComputer(); 
$plane -> takeOff(new Plane()); 

The high-level module, which is the OnBoardComputevvr class, depends on the low-level module – Engine class. While application is expanded, it is not possible (without making changes in OnBoardComputer class) to add another class. Such class could be responsible for wheels concealing in the chassis (this element also occurs during the start of plane!). The solution to this problem is to introduce the interface implemented by the lower-level class – Engine. This interface will cause any class that implements it to implement the startEngine() method. We assume that it will not be possible to start the engine without the engine starting. For example to hide the wheels of the chassis;). At the OnBoarComputer class level, there is a dependency on the interface (from an object compatible with the OnBoarComputerService interface). Below is the source code according to the DIP rule:

class Plane
{
}

interface OnBoardComputerService
{
public function startEngine(Plane $plane);
}

class Engine implements OnBoardComputerService
{
public function startEngine(Plane $plane)
{
echo 'Starting engine!';
}
}

class OnBoardComputer
{
public function takeOff(Plane $plane, OnBoardComputerService $onBoardComputerService)
{
$onBoardComputerService -> startEngine($plane);
}
}
$plane = new OnBoardComputer();
$plane -> takeOff(new Plane(), new Engine());