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.