Decouple your code
Tags: bestpractices, codequality, oop, php
Published: 2019-05-08 11:51:49

---
title: Decouple your code
published: true
tags: bestpractices,codequality,oop,php
canonical_url: https://mindsers.blog/en/decouple-your-code/
---

Decouple your code, your coworkers will thank you.

Decoupling isn't a new concept but I started documenting myself on it fairly recently. Here is what I learned.

## What is "decoupling" ?

To understand decoupling you got to know what coupling code is first.

There is a coupling notion when 2 services with different responsibilities need one another to work. Those 2 services are "coupled".

Our way of dealing with classes will increase or decrease the coupling force:

- a strong coupling is done when classes are initialized inside other classes for example. In general, using classes directly increase coupling. 
- a weak coupling exists when the first class **doesn't know who is and how works** the class she uses.

Example of coupled code :

<!--kg-card-begin: markdown-->
```
<?php

use Config/IniConf;

class IndexController
{
    private $iniConf;

    public function __construct() 
    {
        $this->iniConf = new IniConf('../config.ini');
    }

    public function renderView()
    {
        echo '[' . $this->iniConf->getValue('db') . ' : ' . count($this->iniConf->getValue('db')) . ']';
        echo '[' . $this->iniConf->getValue('name') . ' : 0' . ']';
    }
}

```
<!--kg-card-end: markdown-->

My controller needs to access the app parameters that are stocked into the `.ini` file. No problem because I have a class that does just that : `IniConf`, so I use it. And I do it in several other controllers too: `AboutController`, `AdminController`, `PortfolioController`. Perfect.

But what if I decide tomorrow to change the address of my configuration file? Or if I happen to want to stock my parameters in a database for more flexibility? Do you see where this is heading? Each time, I need to change my controller(s).

The number of code lines I have to change can very quickly became extreme : I will be spending more time changing my controllers than writing the class that stocks the config in database.

## "Decoupling" is the solution

How do you decouple code to limit this type of problem?

You can start by separating `IniConf` and `IndexController`. Of course `IndexController` needs `IniConf` (its dependency) to work properly but it shouldn't be the one initializing it. We will do  dependency injection:

<!--kg-card-begin: markdown-->
```
<?php

// Constructeur IndexController
public function __contruct($iniConf) {
    this->iniConf = $iniConf;
}

```
<!--kg-card-end: markdown-->

There. This way, I can instantiate `IniConf` one time and pass it to the constructors of my controllers. It will limit the number of places I'll need to change the file's address.

For our problem with changing the whole method of parameters saving of the app, let's rewind a bit:

the first class doesn't who is how and how exactly works the class it uses.

It needs to know **the type** of class it needs and how it works. To do that, we will establish a contract between `IndexController` and `IniConf`.

Ways to do that vary depending on the language used : with PHP we will use interfaces, with Swift it will be protocoles.

<!--kg-card-begin: markdown-->
```
<?php

// Contrat

namespace Config;

interface Configurator
{
    public function set($key, $value);
    public function get($key);
}

```
<!--kg-card-end: markdown-->

Whatever my parameter stocking method is, I need to be able to access the parameters and change the keys. You need to create an interface `Configurator` that does that.

<!--kg-card-begin: markdown-->
```
<?php

use Config/Configurator;

class IndexController
{
    private $conf;

    public function __construct(Configurator $conf) 
    {
        $this->conf = $conf;
    }

    public function renderView()
    {
        echo '[' . $this->conf->get('db') . ' : ' . count($this->conf->get('db')) . ']';
        echo '[' . $this->conf->get('name') . ' : 0' . ']';
    }
}

```
<!--kg-card-end: markdown-->

I change the code of my controllers consequently :

- The constructor asks an object that respect the contract `Configurator`
- The controller uses the contract methods rather that the classes' methods.
- The controller doesn't necessarily use `IniConf`, it doesn't know what it uses in fact, we change the attribute in `$this->conf`

The last thing to do is to change the code from `IniConf` to make it respect the contract `Configurator`.

## Conclusion

Code is looking good, it is now decoupled. Nothing changes in the result, the new code does the exact same thing as the previous one but it is simpler to maintain.

My `index.php` code :

<!--kg-card-begin: markdown-->
```
<?php

$conf = new IniConf('../config.ini');
$index = new IndexController($conf);
$other = new OtherController($conf);

$index->renderView();

```
<!--kg-card-end: markdown-->

_The beauty of dependency injection._

I need to change the address of my configuration file:

<!--kg-card-begin: markdown-->
```
<?php

$conf = new IniConf('../libs/config.ini');
$index = new IndexController($conf);
$other = new OtherController($conf);

$index->renderView();

```
<!--kg-card-end: markdown-->

The address is changed in a single place and benefits the entire app.

I migrate my configuration in database.

<!--kg-card-begin: markdown-->
```
<?php

$conf = new BDDConf([
    'dbname' => 'config',
    'login' => 'dbuser',
    'passwd' => '1234'
]);
$index = new IndexController($conf);
$other = new OtherController($conf);

$index->renderView();

```
<!--kg-card-end: markdown-->

Change is transparent for my controllers, I don't change the code. I focused on my new feature (writing class for the new stocking method) and I didn't lose time changing every code line where `IniConf` appeared.

For those of you who would like to see it more in depth, here is the [GitHub link](https://github.com/mindsers/tutorial-decoupling) of the project.