Dependency Injection is Evil

By Tony Marston

3rd June 2011
Amended 8th June 2011

Introduction
What does "Dependency" mean?
What does "Dependency Injection" mean?
What is the problem for which Dependency Injection is the solution?
How can Dependency Injection be implemented?
When is Dependency Injection a good idea?
When is Dependency Injection a bad idea?
Conclusion
My heretical implementation of DI
References
Amendment History

Introduction

I recently came across an article called Learning About Dependency Injection and PHP in the Zend Developer Zone, and several phrases particularly caught my eye:

In any circle of developers that are of the object-oriented persuasion, you'll never hear an argument that dependency injection itself, is bad. In these circles, it is generally accepted that injecting dependencies is the best way to go.

This was closely followed by:

The heart of the argument is not should we be doing it (Dependency Injection), but how do we go about doing it.

Those statements imply that if you are not using dependency injection (DI) then you are an idiot. I take great exception to that arrogant, condescending attitude. Design patterns are an option, not a requirement. Some OO programmers attempt to go a step further by saying that not only *must* you use their favourite selection of design patterns, but you *must* also adhere to their particular method of implementation.

It would appear that I am not the only one who objects to this idea. In Dependency Injection Objection Jacob Proffitt states the following:

The claim made by these individuals is that The Pattern (it can be any pattern, but this is increasingly frequent when referring to Dependency Injection) is universally applicable and should be used in all cases, preferably by default. I'm sorry, but this line of argument only shows the inexperience or narrow focus of those making the claim.

The attitude of these pattern junkies doesn't work with me. *I* will decide whether or not I will use a particular design pattern, and *I* will decide how I implement it. This usually means that I don't use design patterns at all, and those that I do use are implemented in my own unique way. Because of this I am widely regarded as a maverick, a heretic and an outcast by those who consider themselves to be "proper" OO programmers. If you think you have the stomach for it you can read some of my controversial views in the following articles:

I could not let the arrogant statements in Ralph's article pass without comment, so I posted a reply. This was initially passed by the moderator, but was removed 24 hours later. It seems that some OO "purist" objected most strongly to my heretical viewpoint and had my comment removed. This I take as a form of censorship and a violation of my right to free speech. The OO Nazis may think that they have silenced my heretical viewpoint, but they are not the only ones who can publish articles on the internet! Below is my original response to Ralph's article:

This article is yet another glaring example of where OO programmers deliberately try to make a mountain out of a molehill just to prove how clever they are. To me it proves just the opposite.

In my long career in software development I have learned to follow a number of key principles:

  1. If it ain't broke don't fix it.
  2. If it doesn't cause a problem it doesn't need a solution.
  3. Keep It Simple, Stupid!

This "solution" is supposed to address the problem of dependencies, but what exactly is the problem? You cannot eliminate dependencies altogether as your software just would not work. If module A needs to perform some processing which is already contained within Module B then Module A simply calls Module B. This may create a dependency, but so what? It's certainly better than having the code within Module B duplicated within Module A. This is what "Modular Programming" is all about, and Object Oriented Programming is supposed to be an extension of this paradigm by using "objects" instead of "modules".

The idea that you need to "manage" dependencies is also ridiculous. If I have the following code in Module A:

$objectB = singleton::getInstance('classB');
$result = $objectB->doStuff(...);

it is simple to understand and easy to modify. So why change to a different method which is less simple? What are the costs? What are the benefits? By introducing another layer of management you are moving towards the situation where there are too many chiefs and not enough Indians. Your application will contain a small amount of code which does useful work and a large amount of code which manages the workers. It will take longer and longer to get things done, and longer and longer to adapt to changes. And you call this "progress"? Pull the other one, it's got bells on!

There's a saying in the world of aviation:

There are old pilots and there are bold pilots, but there are no old bold pilots

In the world of software development we now have:

There are sensible programmers and there are OO programmers, but there are no sensible OO programmers

When you say that "injecting dependencies is the best way to go" you forgot to add "in cloud cuckoo land". Those of us who have to live in the "real" world will continue to ignore such ridiculous concepts while still being able to write effective software.

I shall now follow this brief response with a more detailed critique of this abominable pattern.


What does "Dependency" mean?

Using terms such as "dependency", "coupling" and "cohesion" can be confusing unless you identify exactly what they mean. Some people may never have heard the terms before, while others apply different meanings. Here are some terms and their meanings which I use:

Dependency The degree that one component relies on another to perform its responsibilities. High dependency limits code reuse and makes moving components to new projects difficult. Lower dependency is better.

This term is often interchangeable with coupling.

Example: If ModuleA calls ModuleB then there is a dependency between ModuleA and ModuleB. ModuleA is dependent on ModuleB as ModuleA cannot operate without ModuleB. ModuleB is *not* dependent on ModuleA as ModuleB does *not* call ModuleA. ModuleB should not know or care about the identity of its caller.

Coupling Describes how modules interact. The degree of mutual interdependence between modules/components. The degree of interaction between two modules. Lower coupling is better. Low coupling tends to create more reusable methods. It is not possible to write completely decoupled methods, otherwise the program will not work! Tightly coupled systems tend to exhibit the following developmental characteristics, which are often seen as disadvantages:
  • A change in one module usually forces a ripple effect of changes in other modules.
  • Assembly of modules might require more effort and/or time due to the increased inter-module dependency.
  • A particular module might be harder to reuse and/or test because dependent modules must be included.

Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa.

Example: By implementing the MVC pattern you end up with a series of controller and model components. If a particular controller can only be used with a particular model, or a particular model can only be called from a particular controller, then you have high/tight coupling. In my own implementation I have 40 reusable controllers (one for each Transaction Pattern) and hundreds of database table classes. Each controller can be used with any table class, and each table class can be accessed by any controller, thus I have low/loose coupling.

Cohesion Describes the contents of a module. The degree to which the responsibilities of a single module/component form a meaningful unit. The degree of interaction within a module. Higher cohesion is better. Modules with high cohesion are preferable because high cohesion is associated with desirable traits such as robustness, reliability, reusability, extendability, and understandability whereas low cohesion is associated with undesirable traits such as being difficult to maintain, difficult to test, difficult to reuse, difficult to extend, and even difficult to understand.

Cohesion is usually contrasted with coupling. High cohesion often correlates with low coupling, and vice versa.

Example: In my framework each database table has its own class which contains the data validation and business rules for that table. Thus if I change a table's structure or validation rules I only have to change a single class, and none of the other classes will be affected.

As an example, if ModuleA needs to access some functionality in ModuleB then it is said that ModuleA is dependent on ModuleB. ModuleA consumes the service offered by ModuleB, so ModuleA is the consumer and ModuleB is the dependent.

Here is one way in which this can be coded:

Dependent creation - the 'JIT' method

class Person {
    function doStuff () {
        ....
        $objAddress =& singleton::getInstance('address');
        $address = $objAddress->getPrimaryAddress($customer_id);
        ....
    } // doStuff
} // end class Person

In this example the 'Person' class is the consumer and the 'Address' class is the dependent. Notice that the dependent object is created/instantiated at the last possible moment just before its service is consumed. This is known as the 'Just In Time' (JIT) method of instantiation. An alternative would be the 'Constructor' method as shown below:

Dependent creation - the 'constructor' method

class Person {
    private $objAddress;
    
    function __construct() {
        $this->objAddress =& singleton::getInstance('address');
    } // __construct

    function doStuff () {
        ....
        $address = $this->objAddress->getPrimaryAddress($customer_id);
        ....
    } // doStuff
} // end class Person

Here you see that the dependent object is created within the constructor of its consumer, although the dependent is not actually accessed until later (if at all). I personally do not like this method as it is possible to create an object which is not actually used, which could lead to performance issues. It also prevents me from adding arguments to the constructor of the dependent which are not actually known until I am about to consume its service.

What does "Dependency Injection" mean?

Dependency Injection (DI) is the solution to the principle of Inversion of Control (IoC). It manages the dependencies between objects by creating the dependent objects outside the object which uses that dependency. In other words instead of objects configuring themselves they are configured by an external entity. But why should they be configured by an external entity? Consider the following statements made in Dependency Injection Considered Harmful:

Firstly, an object's interface should define the services that the object requires as well as those it provides.
Secondly, the code that satisfies the requirements of an object by giving it a reference to the services of is collaborators is external to both the object and its collaborators.

I consider both of those statements to be opinions, not rules, and as such I have the right to ignore them, and being a heretic I choose to exercise that right. I particularly dislike the first statement as it clearly violates one of the fundamental principles of OOP, and that is the principle of encapsulation which states that an object contains both data and methods which act upon that data, but that the implementation of those methods is hidden. This is known as implementation hiding (which is not the same as information hiding). In other words a method's signature, the API, identifies what can be done but gives absolutely no indication as to how it will be done. This allows for a method's implementation to be changed at any time without affecting any external entity which uses that method. The external entity should not even be aware that the method requires the use of dependent objects, and therefore should not have to inject those dependencies into the object before the method can be used. When you call an object's method you are effectively saying "Just do it, and I don't care how".

What is the problem for which Dependency Injection is the solution?

In order for me to accept that something is a good idea I need a concrete example that actually makes sense. The only sensible example I have found is the "Copy" program which can be found in Robert C. Martin's The Dependency Inversion Principle. In this the Copy module is hard-coded to call the readKeyboard module and the writePrinter module. While the readKeyboard and writePrinter modules are both reusable in that they can be used by other modules which need to gain access to the keyboard and the printer, the Copy module is not reusable as it is tied to, or dependent upon, those other two modules. It would not be easy to change the Copy module to read from a different input device or write to a different output device. One method would be to code in a dependency to each new device as it became available, and have some sort of runtime switch which told the Copy module which devices to use, but this would eventually make it bloated and fragile.

The proposed solution is to make the high level Copy module independent of its two low level reader and writer modules. This is done using dependency inversion or dependency injection where the reader and writer modules are instantiated outside the Copy module and then injected into it just before it is told to perform the copy operation. In this way the Copy module does not know which devices it is dealing with with, nor does it care. Provided that they each have the relevant read and write methods then it will work. This means that new devices can be created and used with the Copy module without requiring any code changes or even any recompilations of that module.

Although this example identifies a particular set of circumstances in which dependency injection does actually supply a genuine solution, there are too many dunderheads out there who seem to think that DI must be used in all circumstances even though there may not be any actual benefit! And these people call me crazy!

In Design pattern - Inversion of Control and Dependency Injection I found this description:

Consider the example where we have a customer class which contains a 'clsAddress' class object. The biggest issue with the code is tight coupling between classes. In other words the customer class depends on the address object. So for any reason address class changes it will lead to change and compiling of 'clsCustomer' class also. So let's put down problems with this approach:

Of all the statements in that quote I can only find one with which I agree: the customer class depends on the address object. All the others are questionable.

The biggest issue with the code is tight coupling between classes
That's a wild assumption. How can you possibly determine that the coupling is tight? Coupling describes the degree of interaction between two modules, and it may be either high (tight) or low (loose). If you say that B is tightly coupled to A you are implying that the coupling is so tight that B can only be coupled with A and cannot be accessed from any other module within the system. If my objects contain methods which are highly reusable then the coupling is in fact low, which makes this statement totally incorrect. I can call my $objAddress->getPrimaryAddress() method in any object that contains $customer_id, so how is it tightly bound to the customer object?
So for any reason 'clsAddress' changes it will lead to change and compiling of 'clsCustomer' class also
Why should this necessarily be the case? If I change the internals of the Address class without changing the method signature used by the Customer class, then why should I have to recompile the Customer class at all, especially when I'm using PHP which is interpreted and not compiled? One aspect of encapsulation is implementation hiding where I expose an object's methods but not how those methods are implemented. This allows me to change the implementation of any method at will without having to change any module which uses that method.
The biggest problem is that customer class controls the creation of address object
Why is this a problem at all? It is considered good practice to instantiate an object only when you are about to use it (refer to the JIT method), so putting it somewhere else where it may be instantiated but not used may lead to performance issues as well as maintenance issues.
Customer class is aware of the address class type
Again, so what? In the real world customers have address, so our objects must reflect that relationship, which means that the customer object must communicate with the address object at some point in order to obtain the customer's address.
If we add new address types like home address, office address it will lead to changes in the customer class also
You must have a peculiar way of writing code as in my implementation I can add as many new address types as I like without having any effect on the customer class. Perhaps it's because I had the foresight to define the 'getPrimaryAddress' method so I could differentiate between secondary address, delivery address, billing address, et cetera.
customer class is exposed to the actual address implementation
This is a meaningless accusation which describes a non-problem. The fact that the customer class calls a method on the address class does not tie the customer class to a particular implementation of that method. If the implementation of that method were to change at all, the change would be transparent to the customer object. Provided that the method name exists and that the method, when activated, does actually return the specified address, then how that method is implemented within the address object is totally transparent and totally irrelevant.

As you can see from the above list all the "problems" identified in that article do not exist in my application, so if the problems do not exist then can you please explain to me in words on one syllable what benefits I would obtain by implementing this solution?

How can Dependency Injection be implemented?

Ralph Schindler's article contains the following code snippet as a "solution":

A sample Dependency Injection Container (DIC)

// construction injection 
$dependency = new MyRequiredDependency; 
$consumer = new ThingThatRequiresMyDependency($dependency);

This looks extremely simple, but the simple fact is that it is too simple. Rather than providing a workable solution it simply hints at what part of one might look like, so it does not go far enough. As far as I am concerned it produces more questions than answers.

  1. The article talks about a Dependency Injection Container (DIC), so is there one container for the whole application, one container for each consumer, or one container for each dependency?
  2. Is the contents of each DIC hard coded (as in that example) or can it be provided from a configuration file?
  3. If it's hard coded then surely all you've done is move the tightly coupled dependency from the consumer object to the DIC?
  4. Is the dependent object created at the same time as the consumer object or much earlier?
  5. If it is much earlier then what object is responsible for creating the dependency and what object is responsible for creating the consumer? Must they be the same or can they be different?
  6. If they are different then how is the dependent object passed down to the consumer?
  7. What happens if the consumer object decides in its logic that it does not actually require to communicate with the dependent in the current processing cycle? Surely this means that you have created an object unnecessarily, and this would have an impact on performance.
  8. What happens if the constructor of the dependent requires arguments which are not available until the consumer is just about to communicate with that dependent?
  9. What happens if the consumer has dozens of dependencies? Surely having a constructor with that many arguments hints at code smell?
  10. The example shows construction injection, so where are the examples of setter injection, interface injection and call time injection?
  11. If there are multiple types of injection (constructor, setter, interface, call time) then when would one type be better than the other and why?

Questions, questions, and yet more questions. This article has *NOT* convinced me that dependency injection is a good thing at all, nor has it provided me with sample code that I can try out myself to see if any of the claims can be substantiated. I therefore consider the article to be a waste of space and unworthy of serious consideration, especially from an OO heretic such as me.

It should also be pointed out that DI does not remove any dependencies, it merely separates the dependent's creation from its consumption. The consuming object is still dependent on the dependent object, it just doesn't control when and how it is created. Also, the number of changes you can make in the DI container without having to make corresponding changes in the consuming object are rather limited.

  1. You cannot inject additional objects.
  2. You cannot remove the injection of existing objects.
  3. You cannot change the interface (the API name, or the list of arguments) on any dependent call.

When is Dependency Injection a good idea?

It is not good enough to say "Here is a design pattern, now use it" without identifying under what circumstances it is designed to provide some sort of benefit. If you don't have the problem which this design pattern is meant to solve then implementing the solution may be a complete waste of time. In fact as well as being a total non-solution it may actually create a whole new series of problems, and that strikes me as being just plain stupid. But what do I know, I'm just a heretic!

After searching through various articles on the interweb thingy I discovered that the benefits of DI are, in fact, extremely limited. In Jacob Proffitt's article I found the following:

The real reason that so many developers are using DI is to facilitate Unit Testing using mock objects.

A similar sentiment can be found in Jordan Zimmerman's article Dependency Injection Makes Code Unintelligible:

DI has gained support from the Test Driven Development community as it makes running tests easier.

So there you have it. DI does not provide any benefits outside of a testing framework as its only function is to provide the ability to switch easily between a real object and a mock object, but what if you don't use mock objects at all? What if you have found an alternative method of switching to a mock object which doesn't require the use of a DI container (as in the TypeMock framework)?

The idea of using mock objects to perform your unit testing strikes me as peculiar as all you are doing is testing your mock objects instead of your real ones. If you think you need to use mock objects to emulate database access then your entire architecture is wrong. I personally build all my software using the 3-Tier Architecture where I can have as many objects as I like in the Business layer, but only 1 object in the Data Access layer. Thus if I wanted to exchange real database access with dummy database access where would I make the change? All 200+ objects in my Business layer, or just the 1 object in the Data Access layer? Why should I then implement a mechanism to change every object within my application when all I really need to do is change one?

When is Dependency Injection a bad idea?

As well as identifying when a particular design pattern may be a good idea it is also necessary to identify under what circumstances its use may be totally inappropriate, or its benefits either minimal or non-existent. In What is Dependency Injection? by Jakob Jenkov I found the following:

Dependency injection is effective in these situations:
Dependency injection is not effective if:

So if DI is only useful when you need to change your dependency configuration (such as when using mock objects), but in real life such changes are rarely necessary, then is the benefit of implementing DI worth the cost? If you build in, at great expense, the ability to make certain changes in your application architecture, but those changes are rarely made, then surely you are violating the YAGNI principle? If your main reason for using DI is that "DI enables change", are you saying that you cannot make changes to any of your dependencies without DI? If so then you are seriously wrong! If I have to change any dependencies at all in my applications then I can do it far quicker and cheaper the old-fashioned way than using an expensive DI framework. As far as I am concerned DI provides negative benefits with significant costs, so it is simply not worth the effort. But what do I know, I'm just a heretic!

The biggest drawback of dependency injection is that you need a dependency injection container, and you need to configure it. The wikipedia article contains the following:

However, there should exist a definite reason for moving a dependency away from the object that needs it. One drawback is that excessive or inappropriate use of dependency injection can make applications more complicated, harder to understand, and more difficult to modify. Code that uses dependency injection can seem magical to some developers, since instantiation and initialization of objects is handled completely separately from the code that uses it. This separation can also result in problems that are hard to diagnose. Additionally, some dependency injection frameworks maintain verbose configuration files, requiring that a developer understand the configuration as well as the code in order to change it. For example, suppose a Web container is initialized with an association between two dependencies and that a user who wants to use one of those dependencies is unaware of the association. The user would thus not be able to detect any linkage between those dependencies and hence might cause drastic problems by using one of those dependencies.

When some people give examples of where DI can be used to solve a problem they infer that it is either the only solution or the best solution. A common example is where an object uses a separate Data Access Object (DAO) in order to communicate with the physical database, and it requires the ability to switch from one database provider (e.g. Oracle) to another (e.g. SQL Server). I have news for you guys - in my own framework I built in the ability to switch from one DBMS to another with a single change to a config file. That was the only place in my entire application where I could guarantee that a different implementation would be required, so it was the only place where I built in this ability, and all without the whiff of dependency injection!

Conclusion

So there you have it. Dependency Injection is not a foregone conclusion, it needs to be justified. Unfortunately most OO programmers do not have the brain power to evaluate DI to see if it would actually provide any benefit in their particular circumstances. Either they are told by a supposed "superior" that they should implement it, in which case they obey without question just like a bunch of trained monkeys, or they hear about a new 'cool' design pattern and they rush to implement it just to prove to their peers that they are pattern experts.

Ralph Schindler's article Learning About Dependency Injection and PHP, and his follow-up article called DI, DiC, & Service Locator Redux, is full of smoke and mirrors and no substance, and without proper substance I cannot take DI seriously. As far as I am concerned it is just a big joke, a big con, just like most of the other design patterns. This is another one to be added to my "to be ignored" list.

As far as I am concerned using this pattern does not solve a problem, it merely moves some code to a different part of the application and thus creates a different class of problem. The dependent object still needs to be instantiated, so if you move this action to a DI container you are creating the "problem" of having to manage and configure this container. Is it really worth the effort?

I remain unimpressed. I do not see myself rushing out to implement this pattern any time soon, if at all. To quote the Hollywood Principle: "don't call me, I'll call you", but don't hold your breath.

My heretical implementation of DI

Having said that I would never find a use for Dependency Injection it suddenly crossed my mind that there is an aspect of my development framework which, if you squinted and looked at it sideways through a cloud of smoke just might be confused with a form of DI. Well, sort of.

My framework, as well as being based on the 3 Tier Architecture, also contains an implementation of the Model-View-Controller design pattern. My main application contains over 1500 tasks (user transactions), and each task implements a particular Controller with a particular Model and a particular View. In this scenario the controller is the consumer while the model and the view are its dependents. In other people's implementations I have seen them hard-code the identity of the model and the view within the controller, which means that there is a separate and unique controller for each task, which in turn means that none of the controllers can be reused. I did not want this limitation in my framework, so I devised a solution without even knowing that the term "dependency injection" existed, let alone that there was a design pattern for it.

My solution produces a very high level of reusability:

I achieve this by having an additional component for each task called a component script which tells the Controller which Model and which View to use. Thus my component script plays the part of a Dependency Injection Container because it 'injects' (sort of) the dependents (the Model and the View) into the consumer of those dependencies (the Controller). I say "sort of" because my implementation is bound to produce howls of rage from the OO purists as it does not contain a single line of code that can be called Object Oriented by any stretch of the imagination:

angryface (2K)

raspberry1 (2K)There may be other rules that I have violated, but I really don't care. I can make my consuming components (the Controllers) work with any dependent components (the Models and the Views) without touching the internals of any consumer, so as far as I am concerned I have achieved the necessary objective of maximum reusability with minimum effort. My implementation may break your rules, but my results speak for themselves, and as far as I am concerned the results are far more important than your silly rules!

Another place where I use a form of dependency injection is with my View components. The Model is instantiated and filled with data by the Controller before it is injected into the View where the data is extracted before being formated for output.

Here endeth the lesson. Don't applaud, just throw money.


References

It appears that I am not the only one who is not impressed with the idea of Dependency Injection. Here are a few articles I found on the interweb thingy:


© Tony Marston
3rd June 2011

http://www.tonymarston.net
http://www.radicore.org

Amendment history:

08 Jun 2011 Added My heretical implementation of DI.

counter