Dependency Injection Breaks Encapsulation

I am not lying. If you read what I wrote you would see that what I actually say is:

DI breaks encapsulation - under some circumstances
DI is evil - under some circumstances.

On a public discussion forum, where you are dissuading people from using DI and then getting upset whenever someone tells you you’re wrong…

That is the whole purpose of this discussion - to identify when it is appropriate to use DI and when it is not. All you keep repeating is that it is never inappropriate to use DI, and this is where I have to disagree. I am trying to present logical arguments, but you keep twisting everything I say.

I thought I’d elaborate on this a bit, as it’s an important distinction. Both of the following examples use encapsulation. The engine is stored inside the Car object, and when the car accelerates, it uses the engine. The difference is tight and loose coupling.

In either case, whenever the car accelerates, the engine is started.

Tight coupling


class Car {	
	public function __construct() {
		$this->engine = new Engine;
	}

	public function accellerate() {
		$this->engine->start();
	}

}

Loose coupling

class Car {	
	public function __construct(Engine $engine) {
		$this->engine = $engine;
	}

	public function accellerate() {
		$this->engine->start();
	}

}

The step that you seem to be missing here is an important one: Objects are not usually created and used in the same place. For example:

class Driver {
	
	public function drive(Car $car) {
		$car->accellerate();
	}
}

In the calling code, with either the loosely coupled, or tightly coupled car implementation the result is identical: The driver has no knowledge of the engine, only the car because the engine is encapsulated in the Car object.

I am not asking for advice on how to use DI, I am asking the question “under what circumstances is DI an inappropriate solution?” All you can do is say “there are NO circumstances where DI is inappropriate”. That does not leave any scope for further discussion.

Actually I’m saying “Show me a situation where another approach is preferable to DI” and you have repeatedly failed to do so. You present singletons, which have been widely discredited for about 10 years as an answer which is utterly pointless as there’s no room for discussion on them. The debate was had over 10 years ago by people far smarter than you or I and singletons lost hands down.

But you still haven’t provided arguments against my reasons for NOT using DI. Pointing me to articles which support your case is a waste of time as I can point to an equal number of artoicle which do the opposite.

singletons are only problematic - in certain circumstances.

As for the law of Demeter - I prefer the Inverse Marmalade law.

The arguments for using DI is that the alternatives are objectively worse because they break all sorts of important programming principles. Law of Demeter and Global State being the two main ones.

Given the two approaches, DI is objectively better because your approach breaks these fundamental principles that create known bad traits. I don’t see how there is any discussion here and you’re not backing up your points with anything more meaningful than “Because i said so” or “I don’t want to”.

Method arguments have nothing to do with encapsulation. Methods, yes, but not method arguments.

No, I said that using DI in an inappropriate place - which may involve constructor injection - has the effect of breaking implementation hiding and therefore breaking encapsulation.

No I am not. Encapsulation has absolutely nothing to do with coupling whether it be tight or loose. My article referred to in post #1 contains clear definitions of dependency, coupling and cohesion.

You keep failing to realise that there is functionally no difference between:

new Person(new Address))

and

new Person(123);

or even

$person->eat($apple);

In all cases the calling code knows about the class API but not what its doing with the arguments. You can’t have your cake an eat it too. Either all of those cases break encapsulation or none of them do.

Knowing about a class API does not break encapsulation. Knowing how a class works internally does. This, for example, breaks encapsulation:

echo $person->age;

Because I have to know about the inner workings of the Person object.

This does not break encapsulation

echo $person->getAge();

Because I don’t know where the age value is coming from, it may be a fixed integer or it might be worked out from their birthday. The point is, the calling code doesn’t care.

I am not telling people “don’t use DI under any circumstances”. I have clearly identified under what circumstances I consider DI to be a good idea, but where those circumstances do not exist I consider the use of DI to be not such a good idea.

Please read what I wrote and stop misquoting me.

You are answering a question with another question, which means that you are evading the original question completely and attempting to steer the discussion in another direction entirely. If you look at the two questions side by side:

  • Under what circumstances is the use of DI inappropriate
  • Show me a situation where another approach is preferable to DI

In answer to your question - another approach is preferable to DI in those circumstances where DI is not appropriate.

I disagree. Singletons are only problematic in some circumstances, not in all circumstances. I suggest you actually read some of those articles you referred to.

[Citation needed].

http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/ does not mention a situation where singletons are preferable

http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx does not mention a situation where singletons are preferable

http://crazycoders.net/the-dangers-of-the-singleton-design-pattern/ vaguely alludes to " ok in the right places" but doesn’t state at all what one of those situations might be

http://codebetter.com/jeremymiller/2005/08/04/chill-out-on-the-singleton-fetish/ says specifically "My best advice is to not use caching via static members until you absolutely have to for performance or resource limitation reasons. " In PHP this is not going to be an issue

https://nikic.github.io/2011/12/27/Dont-be-STUPID-GRASP-SOLID.html Doesn’t mention at all that there is ever an acceptable use-case for singletons.

Wrong again, Tony.

It is not just my opinion that DI is overrated and overused. I suggest you loo at the following

http://www.natpryce.com/articles/000783.html

http://www.innoq.com/blog/hw/2007/08/29/dependency_injection_good_or_bad_practice.html
http://www.elilopian.com/2007/08/19/dependency-injection-keep-your-privates-to-yourself
http://java.dzone.com/articles/dependency-injection-makes
http://blogs.msdn.com/b/simonince/archive/2008/06/30/dependency-injection-is-dead.aspx
http://richardmiller.co.uk/2011/05/19/when-dependency-injection-goes-wrong
http://www.javalobby.org/java/forums/t78371.html
http://johannesbrodwall.com/2010/11/10/this-dependency-injection-madness-must-end
http://devhawk.net/2009/07/17/the-texas-dependency-injection-massacre
http://web.archive.org/web/20130916185759/http://theruntime.com/blogs/jacob/archive/2007/08/07/dependency-injection.aspx
http://web.archive.org/web/20130516130335/http://theruntime.com/blogs/jacob/archive/2007/12/10/dependency-injection-objection.aspx
http://web.archive.org/web/20130516124415/http://theruntime.com/blogs/jacob/archive/2007/08/20/poking-bears.aspx
http://web.archive.org/web/20130516122222/http://theruntime.com/blogs/jacob/archive/2007/12/13/dependency-injection-house-call.aspx
http://comoyo.github.io/blog/2013/02/06/the-inverse-of-ioc-is-control
http://www.loosecouplings.com/2011/02/non-di-code-spaghetti-code.html
http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html
http://www.loosecouplings.com/2011/01/dependency-injection-using-di-container.html

Incorrect. Only one of examples uses DI, but does that example demonstrate a good use of DI? Are you using DI to inject an object that will never be changed to another object? If the answer is “yes” then I would class that as an inappropriate use of DI.

Encapsulation requires you to have knowledge of a class’s methods, but not the code which is behind those methods. This is called implementation hiding.

I disagree. What you bare referring to is information hiding which is not the same as implementation hiding. Read the following articles if you don’t believe me

http://www.tonymarston.net/php-mysql/abstraction.txt
http://web.archive.org/web/20090505194203/http://homepage.mac.com/keithray/blog/2006/02/22/#EncapsulationHiding
http://c2.com/cgi/wiki?EncapsulationIsNotInformationHiding
http://stefanoricciardi.com/2009/12/06/encapsulation-and-information-hiding/
http://nat.truemesh.com/archives/000498.html

I looked at one of the articles to which you referred and it said quote clearly that a singleton is only problematic when you already have a single instance but you want another instance which is not a singleton, but your code won’t let you - it’s either a single or nothing.

I do not have that problem as I can use singleton::getInstance('foo') when I want a singleton and new(Foo) when I do not.

That is not the problem! The problem with singletons is tight coupling!

http://www.natpryce.com/articles/000783.html specifically highlights some flaws in DI frameworks, not DI itself. I agree with the premise, A DI container that uses reflection to write to private properties is doing it wrong. Did you even read this article?

http://www.infoq.com/news/2007/12/does-di-pay-off This is a mostly discussion about Manual injection (e.g. new Foo(new Bar) vs a DI Framework.) no mention of a possible alternative.

https://www.innoq.com/blog/hw/2007/08/29/dependency_injection_good_or_bad_practice.html This is the same article as above, or at least it highlights the same discussion, All we can get from this is that Jacob Profitt is as misinformed as you. no mention of a possible alternative.

http://www.elilopian.com/2007/08/19/dependency-injection-keep-your-privates-to-yourself/ This is again an article that is referenceing the same base article by Profitt. Both profitt’s article and this one miss the point entirely, It’s not about “Changing your code to make it testable” it’s about writing testable code in the first place. no mention of a possible alternative.

http://java.dzone.com/articles/dependency-injection-makes Yet again an article about specific frameworks not the merits of DI itself. It also provides no mention of a possible alternative.

http://blogs.msdn.com/b/simonince/archive/2008/06/30/dependency-injection-is-dead.aspx This is actually an article promoting DI…

http://richardmiller.co.uk/2011/05/19/when-dependency-injection-goes-wrong/ This is actually an article promoting DI… it just highlights some things that you shouldn’t do like breaking LoD.

http://www.javalobby.org/java/forums/t78371.html This is mostly a discussion about specific frameworks, lots of opinions no concrete examples and no mention of a potential alternative.

http://johannesbrodwall.com/2010/11/10/this-dependency-injection-madness-must-end/ mostly highlights issues with a specific DI framework using annotations, which are problematic. Read the comments and you’ll see he misunderstood the testing tool he was using…

http://devhawk.net/2009/07/17/the-texas-dependency-injection-massacre/ This says nothing about DI, it’s about premature abstraction, which sort of related, but adifferent topic.

http://web.archive.org/web/20130916185759/http://theruntime.com/blogs/jacob/archive/2007/08/07/dependency-injection.aspx Finally a real reason! He mentions having to change the code in two places if the constructor arguments change. This is a valid concern, but the alternative (Tight coupling) creates more problems than it solves

http://web.archive.org/web/20130516130335/http://theruntime.com/blogs/jacob/archive/2007/12/10/dependency-injection-objection.aspx This is basically a cut down version of above and just uses your argument “I don’t want to use DI” which is at best pointless when discussing the efficacy of different approaches

http://web.archive.org/web/20121126101433/http://theruntime.com/blogs/jacob/archive/2007/08/20/poking-bears.aspx Same guy again. He’s basically got the same non-arguments as you, only this one is even lighter on the ground…

n.b. all of Jacob Profitt’s articles were refuted here: http://ayende.com/blog/2719/dependency-injection-iamdonquixote

http://comoyo.github.io/blog/2013/02/06/the-inverse-of-ioc-is-control/ this is about DI containers not DI itself

http://www.loosecouplings.com/2011/02/non-di-code-spaghetti-code.html It says the alternative to DI is global state which is very bad but that it’s also possible to misuse DI. Again, it seems to be hinting at Law Of Demeter + DI rather than anything alternative. It’s actually a pro-DI article as it states: “I suspect that much of the antipathy for dependency injection stems from experience with poorly-applied DI.”

http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html This article fully promotes DI! It specificcally states that not using DI is a source of problems

http://www.loosecouplings.com/2011/01/dependency-injection-using-di-container.html This article promotes DI and explains the difference between using a container and not using a container. It’s 100% pro DI and does not mention any possible alternative.

Did you even read these or just paste links you found on google? Half of them oppose the point you are trying to make.

In that whole list there is one very minor valid criticsm which is both easily avoided and does not outweigh the problems introduced by alternative approaches.

The fact that the consuming object is dependent on the called object and this dependency automatically produces coupling is not in dispute. However, I consider it wrong to say that this automatically produces tight coupling. The level of coupling depends entirely on how the relationship between the two objects is coded. If you look at http://en.wikipedia.org/wiki/Coupling_(computer_programming) you will see the following descriptions:

Here is an example of tight coupling:

<?php 
$dbobject = new Person(); 
$dbobject->setUserID    ( $_POST['userID'   ); 
$dbobject->setEmail     ( $_POST['email'    ); 
$dbobject->setFirstname ( $_POST['firstname'); 
$dbobject->setLastname  ( $_POST['lastname' ); 
$dbobject->setAddress1  ( $_POST['address1' ); 
$dbobject->setAddress2  ( $_POST['address2' ); 
$dbobject->setCity      ( $_POST['city'     ); 
$dbobject->setProvince  ( $_POST['province' ); 
$dbobject->setCountry   ( $_POST['country'  ); 

if ($dbobject->updatePerson($db) !== true) { 
    // do error handling 
} 
?> 

Here is an example of loose coupling:

<?php 
require_once 'classes/$table_id.class.inc';  // $table_id is provided by the previous script
$dbobject = new $table_id;
$result = $dbobject->updateRecord($_POST);
if ($dbobject->errors) {
    // do error handling 
}
?>