Coding to Interface
Published: 2019-09-02 13:19:03

---
title: Coding to Interface
published: true
tags: 
canonical_url: 
---

One of the nicest things you can add to your programming skills is **coding to interface**. One of the [five principles of S.O.L.I.D](https://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29) is [Dependency inversion principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle) which states:

> In object-oriented programming, the dependency inversion principle refers to a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. The principle states:[1](https://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29)
> 
> A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
> 
> B. Abstractions should not depend on details. Details should depend on abstractions.

Pretty _formal_ definition hun ? let's understand through example actually.

Imagine we have rudimentary MySQL wrapper class:

```
class Mysql
{
    protected $db = null;

    public function connect($dsn, $user = '', $pass = '')
    {
        $this->db = new PDO($dsn, $user, $pass);
    }

    public function query($query)
    {
        return $this->db->query($query);
    }
}
```

Pretty common and valid code in old days we used to be proud while writing such class. There are couple of problems associated with it though:

- The class `Mysql` has implicit dependency (tight-coupling) on the `PDO` class. All dependencies should always be explicit not implicit.
- It is hard to unit-test due to implicit dependency

Let's use above class:

```
class User
{
    private $database = null;

    public function __construct()
    {
        $this->database = new Mysql();
        $this->database->connect('mysql:host=localhost;dbname=test', 'root', '');
    }

    public function getUsers()
    {
        $users = $this->database->query('SELECT * FROM users ORDER BY id DESC');
        print_r($users);
    }
}

$user = new User();
$user->getUsers();
```

Again pretty common piece of code but again this one has even more problems:

- The class `User` has implicit dependency (tight-coupling) on the `Mysql` class. All dependencies should always be explicit not implicit.
- It is hard to unit-test due to implicit dependency
- If we wanted to change database credentials, we need to edit the `User` class which is not good; every class should be completely **modular** or black box. If we need to operate further on it, we should actually use its public properties and methods instead of editing it again and again.
- Let's assume right now class is using MySQL as database. What if we wanted to use some other type of database ? You will have to modify class.
- The `User` class does not necessarily need to know about database connection, it should be confined to its own functionality only. So writing database connection code in `User` class doesn't make it modular. This defeats the [Single responsibility principle](http://en.wikipedia.org/wiki/Single_responsibility_principle).

You might wonder above code has problems but these days we write code based on MVC design pattern and follow best practices and write _modern code_ but I am sure below code is pretty common even today using any framework you use:

```
class UserController extends Controller
{
    public function actionListAllUsers()
    {          
       // fetch all users from database
        $users = User::model()->findAll();

       // show them on screen
        print_r($users);          
    }
}
```

If you analyze this has same problems again in that class `UserController` is tightly coupled (implicit dependency) with `User` model class which also makes it hard to unit-test.

This means:

> Coupled Code is Evil BIG DOT

## So what's the solution ?

The solution is [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) (see my previous post [Dependency Injection in PHP](http://codeinphp.github.io/post/dependency-injection-in-php/)). The idea behind Dependency Injection is that instead of writing implicit dependencies, we should pass/provide those via constructor or setter method or even interface.

Let's refactor `User` class code and pass our dependency via constructor instead of hard-coding it inside `User` class method:

```
class User
{
    private $database = null;

    public function __construct(Mysql $database)
    {
        $this->database = $database;
    }

    public function getUsers()
    {
        $users = $this->database->query('SELECT * FROM users ORDER BY id DESC');
        print_r($users);
    }
}

$database = new Mysql();
$database->connect('mysql:host=localhost;dbname=test', 'root', '');
$user = new User($database);
$user->getUsers();
```

This is much better! We no more have implicit dependency on `Mysql` class which also makes our `User` class easier to unit-test. The class makes clear intention that it needs some sort of `Mysql` class. It also doesn't know (or care) where `Mysql` will come form, it just needs one to operate. The `User` class is now completely modular and follows single responsibility principle (that of manipulating users).

In the similar way, we can also improve our modern code:

```
class UserController extends Controller
{
    protected $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function actionListAllUsers()
    {          
       // fetch all users from database
        $users = $this->user->findAll();

       // show them on screen
        print_r($users);          
    }
}
```

Here again we pass dependency (`User` class) of `UserController` via its constructor making it much better. So all good ? Not really...

## We still have a problem

One problem with `User` class which still persists is that it is tied to **specific type of database** (`Mysql`). What if we wanted to use some other database like Sqlite or SQL Server or some other ? Well this is where **dependency inversion principle** comes into play.

To overcome this problem, we need to create an **interface** (abstraction or contract - see definition of DIP above) which would allow us to use _any database_ with `User` class. Here is our interface that all databases would implement:

```
interface DB
{
    public function connect($dsn, $user = '', $pass = '');
    public function query($query);
}
```

Here is `Mysql` class now implementing above interface:

```
class Mysql implements DB
{
    protected $db = null;

    public function connect($dsn, $user = '', $pass = '')
    {
        $this->db = new PDO($dsn, $user, $pass);
    }

    public function query($query)
    {
        return $this->db->query($query);
    }
}
```

Another database class implementing above interface:

```
class Sqlite implements DB
{
    protected $db = null;

    public function connect($dsn, $user = '', $pass = '')
    {
        $this->db = new PDO($dsn);
    }

    public function query($query)
    {
        return $this->db->query($query);
    }
}
```

As you can see both `Mysql` and `Sqlite` implement methods imposed by the interface. Finally here is our `User` class:

```
class User
{
    private $database = null;

    public function __construct(DB $database)
    {
        $this->database = $database;
    }

    public function getUsers()
    {
        $users = $this->database->query('SELECT * FROM users ORDER BY id DESC');
        print_r($users);
    }
}
```

Notice that in constructor of above class, we are now passing interface rather than specific type of database.

Now we can use any database for the `User` class, here is example of `Mysql`:

```
$database = new Mysql();
$database->connect('mysql:host=localhost;dbname=test', 'root', '');
$user = new User($database);
$user->getUsers();
```

And example of `Sqlite` database class:

```
$database = new Sqlite();
$database->connect('sqlite:database.sqlite');
$user = new User($database);
$user->getUsers();
```

Amazing! we can now readily change database to be used with our `User` class, our `User` class is much more flexible by following the dependency inversion principle. If client requires to use some other database, no problem we implement one and specify to `User` class in similar fashion!

As you can see we took basic and common example of code and converted it into re-usable, flexible, modular and testable piece of code.

You might want to read more about [S.O.L.I.D principles](https://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29) to write pleasant code and as bonus avoid [S.T.U.P.I.D](http://williamdurand.fr/2013/07/30/from-stupid-to-solid-code/) code.

 ![](http://feeds.feedburner.com/~r/codeinphpfeed/~4/R-HEJrk66Ko)