What problem does dependency injection solve? – Rob Allen's DevNotes


: 9

Zend Framework 2 comes with a dependency injection container (DIC), as does Symfony 2 and Aura, along with many other PHP frameworks that target PHP 5.3 or higher nowadays. This article attempts to explore the problem that a DIC tries to solve.

Consider this simple (contrived!) example of an Album object that has an Artist object:

The question is how to we set the $artist member variable within this class?

There are a number of ways to do this. The easiest way is instantiate it directly:

This is Not Good Code (TM) on a number of levels. The most obvious problem is that suppose that at some point in the future you create a new class, SoloArtist, that overrides Artist, then Album will need to be reworked to handle this situation.

Dependency Injection is the term used when you write more flexible code that allows the dependent classes to be changed without having to change the class' code. There are a number of different ways to inject the artist object into our album. The easiest way is to use a constructor:

The calling code then does this:

One problem with constructor injection is that if your class has many dependencies, then your constructor signature gets unwieldy and hard to read.

Another way is to use setters:

With usage like this:

Now, when you have multiple dependencies that you need to inject, each one is a separate set method and so we don't have a long list of constructor parameters.

However, once you have multiple dependencies, the amount of code that you have to write to use this class gets bigger and bigger. As a result, if you use the class a lot, it ends up that you're writing a lot of extra boiler-plate code every single time; just to configure the class!

The solution to this problem is called a Dependency Injection Container.

A specific container for our Album class could look something like this:

(obviously, this example glosses over a number of real-world considerations…)

Now, to instantiate a new Album object, the code is:

This makes using the class easier and gives us all the benefits of decoupling our dependencies. Having to write a new container class for every object gets old very quickly though and so to solve that, generic dependency injection containers have come into existence.

Hence, a dependency injection container is simply a component that holds dependency definitions and instantiates them for you. That is, it stores configuration information about which dependencies any registered class has and instantiates them according to the definition provided.

Don't write your own though; use one of the many that are out there!

(Yes, I know that there's many many posts on dependency injection out there. There's always room for one more though! I also recommend perusing Fabien Potencier's Dependency Injection with PHP 5.3 talk slides)