Dependency Injection Breaks Encapsulation

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 
}
?> 

This is a very strange example with too much going on that is irrelevant to the point, lets cut it down to what you actually mean so we’re comparing apples to apples:

  1. Tight coupling
$dbobject = new Person(); 
$result = $dbobject->updateRecord($_POST);

Loose coupling:

$dbobject = new $table_id;
$result = $dbobject->updateRecord($_POST);

However, the same loose coupling could be achieved like this:

$result = $dbobject->updateRecord($_POST);

Where $dbobject is defined whereever you were defining $table_id in the first example. Newsflash: This is essentially DI.

I did read those articles, and what is common among them is the idea that blindly implementing DI without investigating the reasons is the problem. DI can provide benefits in some circumstances but not necessarily in all circumstances. The trick is to look at each set of circumstances and evaluate the cost of implementing DI against its benefits.

Robert C Martin’s “copy” program (refer to http://www.objectmentor.com/resources/articles/dip.pdf) gives a perfect example of where DI provides benefits, so you need to look at your code to determine if you have the same set of circumstances as that “copy” program. If you do not then I would say that using DI would not provide any benefit so there would be no point in using it.

Again, you miss a fundamental fact: If you are not using DI you are using another approach to manage dependencies. The efficacy of this approach can be directly compared to the efficacy of DI and when you do this comparison DI comes out on top. There are a few places where DI can be used improperly (E.g. violating LoD and injecting a container instead of the object that’s actually needed) but when you do a like-for-like comparison then the benefits of DI outweigh any proposed alternatives, especially if those alternatives use global state and tight coupling.

Those two pieces of code provide examples of tight coupling and loose coupling as described in that wikipedia article. Tight coupling occurs when one module modifies or relies on the internal workings of another module (e.g., accessing local data of another module).Therefore changing the way the second module produces data (location, type, timing) will lead to changing the dependent module.

This condition is clearly present in my example of tight coupling, and is not present in my example of loose coupling.

You have to eat to live. If you are not eating bread you’re eating something else. We can directly compare the nutritional value of the two meals. How is this such a difficult concept to grasp? If you have two methods of doing the same thing, say curing an illness, it makes sense to directly compare them. To do that we need to know what each method is.

I’m struggling to understand why this is an issue for you.

Do you mean where the implementation is faulty? Or do you mean where DI should not be used in the first place?

Where the implementation is faulty. E.g. injecting a container rather than the actual dependency

I am glad you are a soothsayer. In the real world the requirements change often and sometimes drastically. By building software that is flexible it is more robust. Considering the singleton method takes both more lines of code and adds complexity, yes I would say that even in this situation when you’ll never need to substitute it it’s preferable… simply because it is less work.

It is YOU who is continually missing the point. This discussion is about using DI and not using DI. If I am not injecting any dependencies then I am not using DI. It does not matter what alternative methodology I am using - it could be “new”, it could be a singleton, it could be a service locator, it could be some other fancy design pattern that someone has just invented - the simple fact is that it does not involve injecting anything, therefore it is NOT DI.

Do you mean where the implementation is faulty? Or do you mean where DI should not be used in the first place?

If you are saying that DI always provides benefits then I have to disagree. There are some circumstances where the ability to switch a dependent object to an alternative object is wasted simply because there is no other alternative. In my original example I am using the Address object to obtain an address, and this data can ONLY be obtained from the Address object. There is no other object in the system from which I can obtain an address, so I cannot switch to another object. If I cannot switch then why should I insert code to make that switch easier?

You have to eat to live. If you are not eating bread you’re eating something else. We can directly compare the nutritional value of the two meals. How is this such a difficult concept to grasp? If you have two methods of doing the same thing, say curing an illness, it makes sense to directly compare them. To do that we need to know what each method is.

I’m struggling to understand why this is an issue for you.

Do you mean where the implementation is faulty? Or do you mean where DI should not be used in the first place?

Where the implementation is faulty. E.g. injecting a container rather than the actual dependency

I am glad you are a soothsayer. In the real world the requirements change often and sometimes drastically. By building software that is flexible it is more robust. Considering the singleton method takes both more lines of code and adds complexity, yes I would say that even in this situation when you’ll never need to substitute it it’s preferable… simply because it is less work.

Sorry I accidentally edited rather than added a new post, This was post #77

tony_marston404:
This condition is clearly present in my example of tight coupling, and is not present in my example of loose coupling.
You’re conflating two different issues here. Your argument here, and I agree with you, is that we should program around interfaces. E.g. if you have multiple classes with the same API then we gain polymorphism.

If you couple the code to the interface rather than the concrete class ,e.g. Person then you can just slot in any other class that has the same interface. In my example:

dbobject = new Person();
$result = $dbobject->updateRecord($_POST);
It’s impossible to reuse this code with any object other than Person, which is as you say, tightly coupled.

$dbobject = new $table_id;
$result = $dbobject->updateRecord($_POST);
Here, I can use an instance of any class that implements the updateRecord() method.

And I agree with you. What I don't understand, however, is how you've gone full circle because this, essentially, is exactly what DI is all about. This is basically an example of DI so now I'm very confused.