This is a continuation of the discussion at Dependency Injection: a discussion of the pros and cons which was supposed to focus on the question of DI and the arguments for and against its use, but which degenerated into a series of personal attacks. I would like to see if it is possible to have a civilized debate on this subject, and I have decided to stoke the fires a little bit by saying that, in my humble opinion, not only are there circumstances where Dependency Injection (DI) is not a good idea, but if it is employed in those circumstances it has a nasty side effect in that it actually breaks encapsulation. Before you say that this is a stupid idea, let me say that it is no more stupid than the idea that Inheritance breaks encapsulation (refer to http://en.wikipedia.org/wiki/Information_hiding#Relation_to_object-oriented_programming).
In the article at http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html the author identifies three categories for classes: value objects, entities and services and explains why each of these categories can be treated as either âinjectableâ or ânewableâ. Value objects and entities are newable while services are injectable.
My framework is an implementation of the 3-Tier Architecture (see http://www.tonymarston.net/php-mysql/3-tier-architecture.html) combined with the Mode-View-Controller design pattern (see http://www.tonymarston.net/php-mysql/model-view-controller.html). In this structure all the Model classes, one for each database table, qualify as âentitiesâ while the Controllers, Views and Data Access Objects qualify as âservicesâ.
There are places in my framework where I have found a use for DI, such as injecting my Models into my Controllers and Views, but where I have a Model class which is dependent on another Model class I do not use DI. This follows the loosecouplings rule that âentitiesâ are not âinjectableâ.
This means that code such as the following:
class Person {
function doStuff () {
....
$objAddress =& singleton::getInstance('address');
$address = $objAddress->getPrimaryAddress($customer_id);
....
} // doStuff
} // end class Person
Is perfectly valid as it stands because both the âPersonâ and âAddressâ objects are entities and therefore not injectable.
Although I could employ DI here I do not see the point in doing so as it would be a complete waste of effort. I do not need the ability to switch the âAddressâ object to another object for the simple reason that what I want at that moment in time is an address, and that can only come from the âAddressâ object. The ability to switch to another object would be a pointless as it could never supply an address.
The idea that DI breaks encapsulation comes from the description of implementation hiding which states
In other words, a class exposes its methods, but the code behind those methods should be hidden. This means that if the implementation requires the use of other dependent objects then the caller should not need to specify which objects to use. It should be possible to change the implementation without having any effect on the calling object.
So, there are two points to be discussed:
- Are there circumstances where using DI would not provide any benefits and therefore should not be used?
- Are there circumstances where using Dependency Injection breaks encapsulation?
This is just a summary of the information contained in my article http://www.tonymarston.net/php-mysql/dependency-injection-is-evil.html
@Hall_of_Famer, @swader, @Jeff_Mott, @s_molinari, @fretburner, @cpradio, @DaveMaxwellď˛