Dependency Injection Breaks Encapsulation

Is this really necessary Tony?

The good reasons have ALL been pointed out on numerous occasions. You simply choose not only to ignore them, but to try and condemn them as bad, like in your “DI is Evil” drivel, where you hypocritically admit to even using DI.

Scott

I code a bit, then test what I coded. Then I code a bit more, then test that. If I have an IF statement in my code I try to generate conditions which go down each path. When I have finished coding I look at it to see if it needs refactoring, then I test it again. Then I hand it over to my QA department.

I have tried writing simple tests where I have simple functions which perform algorithms or string manipulation, but as my application deals mostly with HTML forms and SQL statements - for which unit testing frameworks have little support - I would find it impossible to get anywhere near 100% code coverage, so I don’t bother.

Thank you.

Also, that makes a lot of sense. I’ve even found anything dealing with a lot of HTML/SQL statements to still be hard to test against even when in a TDD environment (or an application built using TDD from the ground up). – so I understand that all too well.

Just for clarification, when you say “test what I coded”, you use your UI/framework screens for those tests right? I also take from your workflow that you find testing after small increments in your code is easier so you can quickly test the most recent code path change without having to worry necessarily about all the changes as a whole? Is that a adequate assessment?

I remember when I first started “programming” (if you could call it that back then), I’d write all this work, then go to test it and be lost because it could have failed in 1 of a dozen places. Oh how I quickly learned to test more frequently and in smaller chunks or at least “chunks that could be tested”.

I have never said that the changes to the language are bad, but if all they do is allow me to do what I am already doing, but in a different way, then I have no need for them.

You may think that there are good reasons to use a new feature, but unless the cost of changing my code has visible benefits then I’m afraid that incorporating those changes would not be worth the effort.

I am NOT being hypocritical. If you bothered to read that article properly you would see that I say DI is a good technique when used in appropriate circumstance, but is not so good when used in inappropriate circumstances. I use DI where I have a dependency which can come from several sources, but where a dependency can only come from a single source that will never change then I do not. It is as simple as that, and as an ardent follower of the KISS principle it works for me. You might have a different opinion, but that is your right. But DO NOT try to ram your opinion down my throat as the ONLY opinion that is allowed to exist as it will not get you anywhere.

If I am adding a new set of screens to deal with a new database table then all I do is test those screens. As most of the boilerplate code exists within the framework and is used by all user transactions, then I don’t have to test that boilerplate code again.

If I am changing some business logic in an existing user transaction then I test the whole transaction again by generating test data that goes through all the new logic.

Whenever I change a common library function which is used in a lot of screens then I try to run as many of these screens as I can think of in order to test that the change I have made hasn’t broken anything. To be honest I have to admit that there have been occasions when I have tested a change by running 10 different screens, but an error occurs in an 11th screen which I did not test. and is now being run on a client’s site. Fortunately those errors are rare and easy to fix.

1 Like

But, you still go on to call DI evil and call the people who also use it mindless monkeys, yet you use it (the reasons for when and why are absolutely irrelevant). I call that hypocritical sensationalism.

Scott

When I first started coding with COBOL in the 1970s we did not have monitors, IDEs and interactive debuggers, we had punched cards. We would spend all day writing our code onto sheets of paper from a coding pad, and at the end of the day submit those sheets of paper to the punch girls who would punch the code onto cards which were then taken to the computer room where they were digested by enormous card readers. We would then have our output delivered the next morning on sheets of flowline paper. If it aborted we had an enormous core dump to work through. Thus we had one attempt each day with a turnaround time of 24 hours.

Just contrast that with today where I can write some code, run it and debug it in my IDE, correct a mistake and run it again, all within a matter of seconds. Luxury, pure luxury.

1 Like

Only when it is used in inappropriate circumstances. Those developers who use DI in ALL circumstances, blindly and without thinking, deserve to be called mindless monkeys

I’ll admit that is definitely before my time, but I’ve worked with many Mainframe developers who remember doing their coding that way. The times have very much changed since then (which is very nice).

1 Like

but I’ve worked with many Mainframe developers

Read: @cpradio is too ashamed of his agedness to admit that his “friends” are really himself.

Don’t be ashamed, @cpradio. We venerate age and experience here at SitePoint.

2 Likes

I wish, but the only thing I know about the Mainframe is that I don’t want to work on the Mainframe. :smile: I grit my teeth when I have to login to CICS/TSO to look up policy information…

And in what circumstance is DI inappropriate? I think Tom showed you at least 4 times in this thread that when DI is used, even when it isn’t necessary, it doesn’t do any damage or cause any disadvantages and the alternatives are actually worse. So, when is the use of DI inappropriate? And try to talk in coding terms, like with real code. Get your hands dirty with some DI examples, where DI is actually a really bad idea.

Scott

So if I’m understanding you correctly, your existing code base means that the cost/benefit ratio of applying things like unit tests is too great.

When you are writing new code, are you also using what you call old-fashioned techniques? Just because they’re old-fashioned doesn’t mean that they’re bad, but I’m curious about recently written code whether your coding techniques differ years later, as compared with your legacy code base.

For those you who can’t get enough.

http://www.reddit.com/r/PHP/comments/31ulj7/dependency_injection_is_evil_another_gem_from_the/

I don’t think there is a single individual on the face of this planet that agrees with *most of Tony’s radical views.

One of my favorite pieces is the individual who wrote a script to hack the encryption.

Encryption: http://pastebin.com/2j2G83AH
Hack: https://gist.github.com/ircmaxell/160b4a2f98f56ee6c890

I mean if you say you know so much than someone shouldn’t be able to that easily hack your encytion system. Just saying…

He doesn’t care that no one agrees with him. What I can’t understand is why he is bothering to try to convert everyone else to his view when it ought to be obvious to him by now that no one else is interested in switching to his unique method of coding.

I have already explained several times what I mean by the “appropriate” and “inappropriate” use of DI. I suggest you look at posts #18 and #24,

And Tom asked you both times to explain yourself better with real code examples about where DI would be inappropriate. He came up with code examples, where DI isn’t a problem, even when it isn’t necessary, yet you completely ignored these examples and their meaning to the discussion.

How about being the pragmatist you claim to be, by showing practical code examples, where DI is inappropriate? Even show how it breaks encapsulation.

Scott

Well, I would like to think that we have come a long way from those times. In this time I’ll have to agree with you

:smile:

Wisdom, @jeffreylees, wisdom… He’s very sensitive when you talk about his old age… :stuck_out_tongue:

I have already provided a code sample where I use a dependency without the use of DI (look at post #1), so I am not going to do it again.

If you cannot understand the simple description I provided to explain which circumstances are appropriate and inappropriate for DI, then providing code samples would be a waste of time.

Back to this again. You keep alluding to me being incompetent or having a lack of comprehension skills. You can stop with the indirect insults and the weaseling out of offering concrete examples with my being incompetent in your mind, as a lame excuse.

This is your only “reason” for not using DI. A waste of effort. Your other argument on DI breaking encapsulation was never proven or properly explained either.

I’ll give you one disadvantage that DI may cause. Complication. It makes a system more complicated in some cases.

0:1 against DI.

Tom had shown clearly how DI allows polymorphism, whereas your singleton pattern, in your only bit of example code, does not. What is better, to have an option open to have polymorphism available with DI or to have none at all with a singleton?

1:1 now.

Also, Jeff pointed out, internally declared dependencies can lead to “spooky actions at a distance”. He also said, “a class should make its dependencies obvious.” The spooky action at a distance problem is avoidable with DI and the externalization of dependencies is achievable with DI.

2:1 for DI.

I pointed out modern and modular code should also be testable. It should be possible to test classes as whole units on their own, thus the term unit testing. These classes should be loosely coupled, yet they may have dependencies and would need them for tests to run successfully. This is achievable with and also without DI. In most cases DI makes it easier to test, especially in larger systems. Even Jakob Jenkov says, “You should keep in mind that even if your application may never need a different implementation of some component, it can still be useful to be able to inject different mock implementations during unit testing.”

3:1 for DI.

You point out in your “DI is Evil” article, that Jakob Jenkov notes when DI is not beneficial. What you and he fails to point out is that it also doesn’t seriously hurt or is a major mistake to use it. Not beneficial != evil/ bad.

Still 3:1 for DI.

One advantage of DI not mentioned yet, I believe, is the ability to inject external configuration.

4:1 for DI.

You go on to quote from David Lungren, who says, “Just like any pattern it can become an anti-pattern when overused, and used incorrectly. If you are never going to be injecting a different dependency why are you using a dependency injector?” Again, that doesn’t say it is wrong, just possibly unnecessary. He also never says what incorrect use of DI is. I have yet to read it anywhere, where the argumentation made any concrete sense against the use of DI, except for the added complexity issue.

The cost to use DI is very little. It’s the cost of some added complexity. So the price you pay for using DI is very little. Whereas the gains are greater than the losses.

  • Looser coupling
  • Polymorphism as an option
  • Identifiable dependencies to classes
  • Easier to Test Code
  • Increased Modularity
  • And if you are a fan of AOP, it enables a much easier weaving of aspects throughout the application (oh, and this makes the score 5:1 for DI!)

Scott

1 Like