Dependency Injection Breaks Encapsulation

This again shows an antiquated attitude. Good PHP developers today build bundles/ packages/ libraries/ components, etc. (and then applications), so that the bundles/ packages/ libraries/ components can be reusable for others and for themselves.

A good example I can come up with quickly is the httpkernel component created for the Symfony framework. This component is a core component for other frameworks too, like Silex and Laravel or for applications like Drupal. If Fabien Potencier, the Godfather of Symfony, had your attitude, then probably Symfony wouldn’t be the popular framework it is and none of the work put into it could be reused elsewhere. I am glad most people don’t share your views Tony, otherwise my project would be 1000 times harder to do and I’d have to come up with doing the same thing others have already done, again. You know, the proverbial “reinventing the wheel”. This was a real issue for PHP, as a programming language, many years ago. Those days are over, thank God and thank Composer and great open minds working with the language today. Because of them, we are a lot further. I would bet, if you decided to rewrite your framework from scratch today, you could put it together in a fraction of the time it took you way back when, all because people like Fabien write reusable code first…then applications.

Scott

The problem here is that Tony is stuck in a cyclic argument. He is basically making these statements repeatedly:

  • My code is my business, stop talking about it I’m not interested in changing it
  • Here’s my code, this is how things should be done.

When someone critiques point 2 he responds with point 1.

5 Likes

Agreed. This is also a great example when a “like”, as a post rating, just doesn’t do the post justice. :smiley:

Scott

I have never said that the methods used in my framework are “more correct”, merely that in achieving the objectives of OOP - to increase code reuse and decrease code maintenance - I have used methods which are different. The reason that I keep quoting samples from my framework is to provide code samples from real life situations.

In my article at http://www.tonymarston.net/php-mysql/dependency-injection-is-evil.html I point to the description of DI in Robert C Martin’s “copy” program (see http://www.objectmentor.com/resources/articles/dip.pdf) from which I derive a description where I see DI as being beneficial:

I then show those places in my framework where I employ DI simply because the above description is applicable. I also show places where I could use DI but have chosen not to do so because the conditions in that description are not met.

Your use of “proper” DI implies that there is also “improper” DI. Is this correct?

I never said that I never use DI in my framework, only that I don’t use it in those places where I consider it to be inappropriate and of no benefit.

My point exactly! It is beneficial when used properly which implies that it is not beneficial when used improperly. All I am doing is trying to define what circumstances are appropriate for DI and what circumstances are not.

Let me turn the question around. Under what circumstances do you think that DI is NOT an appropriate solution?

This is the exact question I asked you at least a dozen times in the last thread and you failed to provide any example code. You are the one making this assertion but you have still failed to back it up with anything meaningful.

Edit: To answer this, it is well documented. But the answer is not, as you’re hoping “Don’t use DI”. DI Can be misused… see here: https://r.je/oop-courier-anti-pattern.html and http://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/ the answer is “Only inject things you you really need”, it’s not “Don’t use DI”

Because I only have one object in my application which can provide an address, so the ability to change it to another object would be completely pointless.

That isn’t how I would structure my application. I do not have separate objects for primary address, business address, billing address, delivery address, POBox, etc. I have a single Address object which has a separate method to obtain each address type.

[quote=“TomB, post:11, topic:113596”]
You still haven’t explained how this violates encapsulation: [/quote]
Yes I have. You just haven’t bothered to read it.

“the Person object encapsulates the Address” object. is not what encapsulation is about.

I disagree. Encapsulation is about implementation hiding, and in your example you are effectively saying “perform this operation, and use this object to do it”. The message should be “perform this operation and I don’t care how you do it”.

I disagree. The code $objPerson>getData("person_id=1234"); is simply saying “get me the data for the person whose id is ‘1234’” but it is not defining what other objects, if any, should be used. Using an argument which helps refine an SQL query has got nothing to do with DI, so saying that it breaks encapsulation is plain misguided.

If you mean that my understanding of encapsulation is different from yours, then you are correct. But whose definition is correct in the first place. To me encapsulation is as simple as[quote]
placing all the properties and methods for an entity in the same capsule or class[/quote]
What is your definition?

I disagree. Explaining the theory behind DI is not very good unless you can back it up with samples of working code. I have explained under what circumstances the use of DI would be beneficial, and shown examples from my own framework where the benefits are clearly obvious. I have also explained under what circumstances the use of DI would NOT be beneficial, and shown examples from my own framework where the loss of such benefits has no effect on how the program functions.

I am “sharing” my code as examples to prove a point. I am not saying that you can use my Person class in your application. There is a big difference between the two.

All you are doing is moving the initialisation of the dependent objects from one place to another. You are advocating eager loading whereas I prefer lazy loading.

Encapsulation has nothing to do with the injection of objects into other objects.

You are now just backtracking. This is nothing to do with DI. If by your logic new Person(new Address)) “breaks encapsulation” because the calling code must know that the person needs an address then getData("person=1234") breaks encapsulation because the calling code knows the method needs a string (And this example, a very specifically formatted string!). Your definition of encapsulation is flawed, I suggest you go read up on it. The wikipedia article is a good place to start.

I disagree. Explaining the theory behind DI is not very good unless you can back it up with samples of working code.

And yet you have repeatedly failed to show “samples of working code” I asked you in post 2 of this thread and a dozen or more times in the last thread.

No, yo are coming here and stating “Here’s how you should be coding things” then saying “I don’t want to change my code” whenever someone disagrees with you. It’s a non-sequitur and it’s lead to now 300+ posts of pointless discussion where you continually fail to provide anything useful that isn’t rooted in “My code cannot do that” or “I don’t want to change my code but here’s how you should structure yours because DI is evil”

I’m glad you agree. So by this definition how can injecting an object into a constructor break it?

[quote=“TomB, post:17, topic:113596”]
The foo class now knows about the implementation of the singleton::getInstance method (it knows it returns a Bar instance).[/quote]
It does NOT know how the getInstance() method is implemented, it just knows what it does

Knowing that a particular object has a particular method is NOT a sign of bad coding. It is impossible to write a modular system without such knowledge.

This is EQUALLY TRUE for new Person(new Address))!

Refer to what I have already said several times about implementation hiding.

Again with the backtracking… please actually make a point rather than vaguely alluding to earlier statements.

The question was not “do you think that automatic testing is a good idea?” but “why don’t you use automated testing in your own application?”

Not every programmer is obliged to write code that can be shared by all and sundry. Those who are employed to write proprietary applications certainly do not.

While I have released my RADICORE as open source, which means that you can use it to develop your own applications, your are certainly not obliged to share those applications with others.

You would lose that bet.

You’re contradicting yourself because you’re saying that in new Person(new Address)) this is problematic! Get your story straight

Those of us who write code as a business know that once you have written code that works you need to present a good business case for refactoring that code.

I have never said “Here’s my code, this is how things should be done”. What I have said is “this is how I handle that situation in my code”.

“DEPENDENCY INJECTION BREAKS ENCAPSULATION”
“DEPENDENCY INJECTION IS EVIL”

Don’t lie.