Posts tagged di
In Part 1 of this miniseries, I expounded (it’s better than exploding) about Dependency Injection (DI) and Dependency Injection Containers (DICs). To summarise, DI is an obvious and ubiquitous design pattern used daily by most programmers to allow objects accept their dependencies from an external agent (e.g. a unit test which needs to inject mock objects). In an application, the ideal external agent is some container that can assemble objects on demand and create the necessary object graph from scratch outside of the application’s control flow. It is this object assembly function that can be fulfilled by a DIC.
For Part 2, we’re going to dig more into what a DIC is and isn’t. I’ve already noted one very simple DIC called Pimple which will continue as one of my reference points since it best illustrates just how simple a DIC can be. In Part 3, we’ll (finally) turn our attention to some actual source code. Baby steps. Parts 1 and 2 should get you thinking so that ZF 2.0′s DIC is a lot easier to understand and critique. We don’t want anyone panicking just by throwing them into the deep end .
Make sure to read Part 1 if you haven’t already!
Things Which Are Not A Dependency Injection Container (DIC)
Now, in explaining a DIC it’s worth noting there are related solutions which you should find very familiar.
You could use lots of Factories (classes or methods on a class in which the logic necessary to create an object is packaged for reuse). If you followed Part 1, you’d soon realise that the Pimple DIC, as simple as it is, looks very much like a collection of Factory Methods (as Closures). Zend_Application also appears to use Factory Methods or Classes to generate its resources. Along this line of thinking, a DIC is a container of executable Factories. These tend to be the simplest kind of DICs since they rely on source code instructions which can be combined in sequence to assemble a final dependent object and its injected dependencies.
The differences however all come back to the concept of an “external agent”. Factories are traditionally executed within and by an application object whereas a DIC operates from outside an application. Since this is a simple inversion of control, DICs following this mechanism can be written over a coffee break since it’s just a matter of aggregating and mixing Factories – or you can just standardise on Pimple .
Another possible solution is to use a Service Locator. This is often interpreted as an object which can create and retrieve objects. The Service Locator is injected into dependent objects as needed so they can lookup their own dependencies. For example, in our earlier Leprechaun class example from Part 1, we could have created a Service Locator capable of creating Pot classes, injected it into Leprechaun, and allowed the Leprechaun class to lookup whatever Pot it needs.
This too looks very similar to how a DIC appears to operate. It’s also similar to a Factory Class except it can construct many kinds of objects instead of just one particular type. A Pimple container, for example, can be passed into other objects which in turn can ask it to retrieve necessary objects or dependencies. The same holds true of Zend_Application’s resulting bootstrap object. So, in yet another line of thinking, a DIC is always a potential Service Locator – the difference is that we generally don’t inject DICs into dependent objects but allow the DIC create the dependent object from the outside (i.e. it’s an external agent).
In summary, a Dependency Injection Container is not simply a standalone invention – it’s a combination of a few well known patterns we use in PHP that, when combined, create something greater than its individual (and obvious) parts when acting solely as an external agent. That helps explain why most DICs you look at feel a bit too complex. You might see the simple task it performs but not quite grasp why it needs to be so complex until you realise it’s a combination of patterns. We’re used to seeing the constituent patterns isolated and scattered across our application – not brought together in one single entity.
The primary differentiating factor from the simpler patterns, especially Service Locators, lies in one simple concept: Is our DIC truly an external agent? All other solutions tend to require the container to be an internal agent, i.e. a dependency of other objects. Service Locators are injected into dependent objects, and Factories are called from dependent objects.
External Agents See The Bigger Picture
The ideal DIC is an independent external agent. I use the term “external agent” a lot because it’s a good description that’s easy to grasp. The idea is that the DIC creates all other objects, and their dependencies, and will inject the correct dependencies into the right dependent objects. In other words, it’s a master manipulator orbiting our application but not actually embedded in it. In a framework, it would be used to create almost everything without the rest of the framework even being aware of its existence. Nearly all other possible solutions can’t operate in this fashion. A Service Locator must be embedded into other classes and Factories are all called from within other classes too, i.e. they are internal agents…not external.
Now, programmers have two fundamental questions when it comes to basic OOP:
1. Where do I create objects?
2. How do I transport objects across application layers?
DICs answer the first question. You can create objects using a DIC which is independent of the application. It’s our external agent. They also answer the second question. In applying Dependency Injection, your DIC knows how to inject dependencies into the objects needing them, even if those objects come from different layers of the application. This should render the need for Service Locators, Factories, and the always popular Registry pattern almost defunct.
This is what makes the concept of Dependency Injection and DICs useful in frameworks. If you’ve ever used Zend Framework before the arrival of Zend_Application you’ll be familiar with the two questions from above. Creating and transporting objects was an unanswered question at the time, with users running in all directions using Registries, Service Locators, In-Controller instantiation and bootstrap instantiation (mixed with non-static Registries and the handy FrontController parameter transport) – and that’s just the generic groups. In reality, people developed dozens of varying implementations on these themes. This lack of consistency was an irksome problem. By implementing good DICs, both Symfony 2 and Zend Framework 2.0 have settled on one consistent direction.
However, using a DIC in its designed role requires something of a leap of faith. PHP programmers use Service Locators, Factories and Registries all the time. We’re comfortable with those patterns and many of us will always crave their simple natures even when we understand why Dependency Injection is a better solution. This craving can end up corrupting the idea of DI by implementing a common antipattern: turning the DIC external agent into an internal agent.
DICs As Dependencies Are Evil: They Are Not Service Locators
For example, bearing in mind my earlier creation/transportation question duo. Let’s say we create a NewsletterController in a Zend Framework 1.x application using a DIC like Pimple. Our Controller requires an instance of Zend_Mail for its emailAction method. How do you get the Zend_Mail object into the Controller? Well, using Dependency Injection the answer is very obvious – you define either a setter, a constructor parameter or a public property on the Controller class. Then you can program Pimple to a) create the Zend_Mail instance, b) create the Controller and c) inject the Zend_Mail instance into the Controller (e.g. using a setter method). Creation and transportation are neatly solved. The best part is that none of the participants are aware of the DIC, the acid test being that anything a DIC can do, you could have done it by hand without a DIC (hint: a DIC can replace a lot of what ZF users would normally call bootstrapping).
Both Zend Framework 2.0 and Symfony 2 optionally allow another possibility. When we create the NewsController, we can inject the DIC into the Controller itself. This would allow the Controller to lookup resources from the DIC instead of the DIC injecting them from outside the Controller, i.e. our external agent just became an internal agent.
The switch may appear very convenient and comforting. Instead of all this running around with a DIC magically creating Controllers, you could have a typical Dispatch/Execute cycle and add the code for object creation/retrieval into your Controller actions. This has benefits – object creation is clearly visible in all your controllers. However, your intuition is slightly off base.
Firstly, this isn’t Dependency Injection. Our dependent objects have now internalised dependency creation. Since it’s not DI, a DIC is obviously a misplaced tool. So instead of a DIC, you are actually mutating it into a Service Locator. The side effects of eliminating DI are to make it harder to understand dependencies (not easier as you might suspect!). A Service Locator just needs a name to lookup – there are no setters or constructor parameters with typehinting or useful Docblocks to refer to. So your intuition was wrong – it might make your life easier, but everyone else who lacks your familiarity with the source code you’re writing will spend a lot of time dissecting your DIC to figure out what the concrete dependencies really are. Yes, it’s the age old justification for many practices these days – ensuring the long term costs of change are minimised.
Secondly, it creates objects which are useless without the specific DIC interface it depends on. Given an application tends to use only one DIC, importing classes from other sources which need a completely different DIC in order to work is a PITA. Classes which don’t need to be framework specific MUST NEVER be framework specific (i.e. frameworks all use different DICs and depending on one excludes using your classes with another). If classes are DIC specific – you have done something horribly wrong in practicing OOP (and by extension DI).
This is very similar to my past arguments as to why my idea of Zend Framework Modules does not include Libraries/Components. Apples and oranges. Putting a generic library into any form of framework specific packaging or tying it to a framework specific import/DIC mechanism is just plain wrong if it restricts reuse outside of your preferred framework. It gets a lot worse should such dependencies expand from your Controllers (where they could be restricted in practice) to your service/model layer which shouldn’t be aware of the framework at all!
Thirdly, DICs are really bad Service Locators. Since your average DIC likely knows almost everything about objects in the application across multiple application layers (by design since it’s an external agent with that specific purpose), any object into which a DIC is injected might now have access to any other object the DIC knows about. This is crazy. If every object can access every other object, it will result in the same thing as having every function able to access every other function (which we endured before PHP got a good OOP model): Spaghetti Code.
Then again, the Flying Spaghetti Monster might be offended by good OOP…
The potential for enabling Spaghetti Coding, DIC/framework specific dependencies, and elimination of Dependency Injection practices are all serious issues – which is why injecting DICs into any other object outside a controlling bootstrap mechanism used to initiate the DIC and get your MVC framework prepped is referred to as an anti-pattern by some. It’s a Bad Thing.
Why Do Frameworks Enable Bad Practice?
Why is water wet? Frameworks operate to a specific set of needs: a compromise between the ideals of the developers and the needs of the users. The goal of a framework is not to hold your hand 100% of the time but to offer an opinionated (all of them are to some degree!) framework which developers hope is capable of meeting a broad set of user needs so that you can get your application off the ground on the cheap and focus on developing your application’s model. Since many PHP programmers will very quickly want the DIC-Injection anti-pattern, frameworks will inevitably offer it. It may not be considered good practice, but it’s one that nearly all PHP programmers have used to some degree. The trick is knowing whether the cost is worth it and, if not, how to opt-out of (or avoid opting-in to!) the anti-pattern.
If it makes you feel any better, framework developers spend an inordinate amount of time debating similar topics. We’re not out to hang you but compromise and education are often a better solution to being overly restrictive. In reading this topic, I hope this little slice of education will inform you on future decisions around how to recognise, implement and use DICs. Even if you wrote it over your coffee break.
In any case, in Part 3 we’ll meet Zend\Di. Code at last .
If you’ve been watching the PHP weather vane (we call it Twitter for short), you may have noticed a shift in Symfony and Zend Framework. Version 2.0 of both web application frameworks feature Dependency Injection Containers (DICs) as the primary means of creating the objects (and even Controllers) your application will use. This is an interesting shift in a programming language that often stubbornly evaded adopting DICs to any great extent. In this mini-series of articles, I’ll take a look at the marvellous world of Dependency Injection as we run up to an examination of Zend Framework 2.0′s Zend\Di component in the next part.
What is Dependency Injection (DI)?
The short answer to this question is that Dependency Injection is a design pattern where, instead of dependent objects creating their dependencies internally, they instead define setters, constructor parameters or public properties which allow a user to “inject” dependencies from the outside into the dependent object and where such dependencies adhere to an expected interface.
If the definition sounds familiar, it’s because Dependency Injection is an obvious design pattern. As a programmer who knows how to use PHPUnit, you probably use the pattern every time you open an editor. So let’s quickly look at why the pattern is both obvious and ubiquitous.
Imagine a class implementation called Leprechaun. In writing the class, we realise we have a dependency on another class called PotOfGold. A naïve implementation would start out very simply with the Leprechaun object creating an instance of PotOfGold for use.
If you think this through, you may notice the problems. What if we want our Leprechaun to instead have a PotOfRareEarthElementsFromChina? What if we need to replace PotOfGold with a mock object during unit testing? What if another users locates a bug in PotOfGold and needs to replace it without editing the original class (since it’s under 3rd party version control)?
The answer to all these questions is to allow external parties to inject dependencies instead of relying on the object to create them internally. Based on our ridiculous example from above, we would define a setter called setPot(), and allow it to accept any object which implements a new Pot interface. Using an interface merely ensures the dependency that is set obeys some interface the dependent object is expecting.
That, in a nutshell, is why Dependency Injection is obvious. It’s a simple shuffling of creational responsibilities from within an object to some external agent which makes the dependent object more flexible, testable and amenable to the wisdom that Composition is preferred over Inheritance (i.e. injecting objects beats monkey patching!).
Some External Agent
In applying Dependency Injection, we eventually reach a state where all objects in a system are created by a mysterious external agent. What is this entity?
One possible candidate is whatever passes for a Controller in your framework based application. In Zend Framework, this would be an instance of Zend_Controller_Action. Our Controller, in this instance, would define an action method which would perform a necessary application task and create all the objects needed to perform that task. This makes a lot of immediate sense to programmers since allowing you to write Controllers with as little fuss as possible is a fundamental goal of any framework.
However, Controllers are objects! If you had a NewsletterController defining an emailAction method, you might expect that creating an instance of Zend_Mail inside that action is obvious (which it is). Think again! In Dependency Injection parlance, your Controller is a dependent object and an instance of Zend_Mail is one of its dependencies. This is no different from our Leprechaun example. If we create the Zend_Mail instance inside the Controller we get the same irritatingly stubborn question. How do we replace the Zend_Mail instance with an alternative, test double or monkey patched version containing an emergency bug fix?
Controllers, alas, are not the external agent we’re looking for to create objects. And yes, you really should be testing your Controllers .
The next entity a level above Controllers can be loosely termed the Bootstrap. In Zend Framework 1, this started out as a relatively simple script to do just enough that you could start the FrontController and dispatch a request. In other words, Zend Framework traditionally did not offer a final external agent as needed for Dependency Injection. It left it to individual users to create something of their own or, as became inevitable, to just create objects in the Controllers themselves.
More recent Zend Framework versions offer Zend_Application, a method of bootstrapping that allowed users to define Resources, i.e. using a method or class which created an object (and injected its dependencies) and returned it on demand when it was needed by a Controller. This was the first consistent approach to handling object creation in ZF which effectively involved defining any number of Factory classes or methods in one location and passing the managing object (the Bootstrap) around the application wherever specific objects needed to be retrieved. In effect, this was a Dependency Injection Container. So, surprise, users of Zend Framework already have a DIC. An even lesser surprise: Zend Framework 2.0 will be no different.
Dependency Injection Containers Are The Devil
The concept of a Dependency Injection Container (DIC) is to act as a programmable object assembler. You take your DIC, tell it how to construct objects (including how to construct and inject their dependencies), pass the DIC to wherever it’s needed, and eventually ask it to create an object it knows about. This is not rocket science. DICs are simple animals to understand, however the devilish suspicion that PHP developers have for DICs is not rooted in what they do but how they do it and whether they make a developer’s life easier.
There’s a widely known belief that the Ruby language doesn’t need a DIC. I’ll use Ruby as an example because it has a few features PHP programmers can salivate over (like how it uses a new method for classes vs PHP’s new keyword making class subsitutions stupidly easy). One investigator of Dependency Injection from the Ruby world is Jamis Buck. For Ruby he wrote two DICs: Copland (a port of Java’s HiveMind) and Needle (it’s like Pimple on steroids which…defeats the purpose). After fighting Ruby for a few years, he finally gave up on trying to write a Ruby DIC and documented his thoughts on his blog in “LEGOs, Play-Doh, and Programming“.
The core lesson from the article holds true even in PHP – by and large, complex DICs are a complete waste of time in most scenarios. Indeed, if you ever use a DIC and discover it requires just as many (if not more) lines of DIC code and configuration as it would to do the same thing in plain old PHP, you should start asking where the fabulous benefits have vanished to because it’s not delaying the onset of cramped finger muscles as advertised.
Most PHP developers understand this instinctively. Unlike Jamis, most PHP programmers probably won’t have a strong Java background. As a programming group, we’re less inclined to assume we need a special DIC blessed by the PHP Gods so we fall back to whatever strikes us as a simpler solution.
But here’s the rub – the simplest solution is itself a DIC.
In referring to Dependency Injection Containers as the devil, cursing their name, and blaming them as Java imports designed to make life more complex than needed, it’s easy to lose sight of the fact that such criticism is about the implementation of DICs and not their actual function. There is nothing wrong with having object assemblers – we use them all the time and call them Service Locators, or Factory Classes, or Zend_Application (Resources), or any of a dozen terms slightly different and probably not entirely accurate. Most of the time we’re trying to create a DIC without being aware of the term.
Needles and Pimples (It’s Not What You Imagine)
Jamis Buck hit the nail on the head back in 2004 with the creation of his Needle DIC Ruby. Instead of creating something inspired by Java that relied on static configuration and too many features, he realised that Ruby excelled (as does PHP to a growing degree – thank Closures) in expressing logic through a Domain Specific Language (DSL). The result was a DIC captured by a simple DSL – well, until he went and overcomplicated it (read his article).
You can see the exact same fundamental simplicity that a DIC is capable of in PHP. It’s a small so-tiny-you-won’t-believe-it DIC called Pimple. Try calling that complex, hard, stupid or any other adjective you might instinctively think of when faced with the term “Dependency Injection”.
The core of Pimple is that you define object creations as closures. This immediately resolves a few traditional DIC problems. There’s no static configuration, you hand code all creation logic exactly once, and objects are named services you can recall and inject into other objects from your closure bodies. It basically takes everything you’d do in creating objects by hand and captures it all in one container. Other than the fact I hate arrays (my version uses object properties instead – it’s 50 lines; nobody was killed during its 5 minute development period), Pimple is like Dependency Injection itself – so blindingly obvious you may kick yourself.
Pimple proves that DICs are not the devil – they can be incredibly simple and useful tools if you can tame the urge to complicate it’s implementation.
Then There Were Frameworks
As you can probably see, making a strong case for DICs is not hard. Dependency Injection is obvious and omnipresent in PHP. Dependency Injection Containers can be a simple 50 line class you can write over a coffee break. The going gets tough when the simple notions we desperately want to cling to meet the complexity of PHP’s now standard tool: the application framework.
Frameworks: Not Written By Monkeys
As we’ve already covered, Zend Framework 1.0 covered off the external agent problem in Dependency Injection by creating Zend_Application. As Zend Framework 2.0 moves towards beta, it also needs a Dependency Injection Container to do similar heavy lifting. This time around, we called a spade a spade and the O’Phinney/Schindler hive mind wrote Zend\Di\DependencyInjector.
The DICs used by Symfony and Zend Framework are not like Pimple. Symfony’s DIC is driven by static configuration (preferably YAML for brevity). Zend Framework 2.0′s DIC is driven by a PHP API (no static configuration). Both have their own set of performance boosting measures to minimise any overhead in using a more complex DIC.
In the next part this mini series, we’ll take a deeper look at Zend\Di and see how it fares compared to Pimple or Symfony 2. In the meantime, I hope I’ve busted a few apprehensions you might have about using a DIC .