Solid Principles in PHP – Dependency Inversion

In this article we come to the D in SOLID, Dependency Inversion and unfortunately this is the most difficult to understand out of all the principles. The principle states that high level modules should not depend upon low level modules. Instead, they should depend on abstractions and not concretions. The low level modules too must depend upon abstractions. In short it’s about decoupling our code.

Now what is high level and low level code. High level code isn’t concerned about the specific details. Low level code is the opposite and that is more intimate with the specifcs and the details. So your high level code should never have to depend upon the low level code. In other words, one class should not be forced to depend upon a specific implementation. Instead it should depend upon a contract, an abstraction or an interface.

Let’s go through an example. What is wrong with the following code?

class PasswordReminder
{
    private $dbConnection;

    public function __construct(MYSQLConnection $dbConnection)
    {
        $this->dbCOnnection = $dbConnection
    }
}

Why should PasswordReminder have any interest is what our database connection is. Like we said previously, high level modules should not depend upon low level modules. In this case the high level module PasswordReminder is depending upon the low level module MYSQLConnection. So what are we supposed to do instead? High level modules should depend upon abstractions, not concrete implementations.

An easier way to understand this is to bring it back to knowledge. Does PasswordReminder need to have knowledge about how you connect to your database? No. It just needs to know that there is some database connection that it can work with. So instead, we would code to an interface.

interface ConnectionInterface 
{
    public function connect();
}

Now if we follow this principle, PasswordReminder to follow an abstraction.

class PasswordReminder
{
    private $dbConnection;

    public function __construct(ConnectionInterface $dbConnection)
    {
        $this->dbCOnnection = $dbConnection
    }
}

The second part of the rule says that low level modules should depend upon abstractions. Now if we create our first implementation:

class DbConnection implements ConnectionInterface
{
    public function connect()
    {

    }
}

we can see now that both the high level and the low level module are depending upon abstractions.

Leave a Reply

Your email address will not be published.