Dependency Injection, or how to make simple concepts sound difficult

Tags:

You may have heard of Dependency Injection. It’s essentially a way to remove implementation dependencies from classes, or “the process of supplying an external dependency to a software component. It is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency.” as Wikipedia puts it.

Sounds complex? Yep. Is it complex? No. You might’ve even used it without knowing about the name.

Three styles

Let’s take a look at the three main styles of Dependency Injection, as listed by Martin Fowler, the simplest first:

  • Constructor injection
  • Setter injection
  • Interface injection

Let’s say we have a class which uses another class to do some task:

class Example
{
    private $_helper;
 
    public function __construct()
    {
        $this->_helper = new MyHelper();
    }
 
    public function doSomethiong()
    {
        $this->_helper->foo();
    }
}
 
interface MyHelper_Interface
{
    public function foo();
}
 
class MyHelper implements MyHelper_Interface
{
    public function foo()
    {
        echo 'Foo';
    }
}

We’ll modify this class to use the three styles of DI…

Constructor injection:

The simplest of them all, simply uses a constructor parameter.

class Example
{
    private $_helper;
 
    public function __construct(MyHelper_Interface $helper)
    {
        $this->_helper = $helper;
    }
 
    /* rest of the class is here */
}

Basically you just pass the helper implementation in the constructor. Could it be simpler than that?

Setter injection:

You might already guess this based on the above…

class Example
{
    private $_helper;
 
    public function setHelper(MyHelper_Interface $helper)
    {
        $this->_helper = $helper;
    }
 
    /* rest of the class is here */
}

So to use Setter injection, you simply need to define a way to set the implementation of the helper with a setter.

Interface injection

Finally, the most complex way of doing dependency injection, interface injection.

interface iInjectHelper
{
    public function injectHelper(MyHelper_Interface $helper);
}
 
class Example implements iInjectHelper
{
    private $_helper;
 
    public function injectHelper(MyHelper_Interface $helper)
    {
        $this->_helper = $helper;
    }
 
    /* rest of the class is here */
}

This is pretty much an interfaced version of the setter injection method.

In closing

So while Dependency Injection is often explained in long articles and so, it’s a quite simple concept.

By using these three methods, we remove the dependency of MyHelper from the Example class. Instead, depending on the environment, we could provide a different implementation of the helper, for example a mock object for running tests.