Daniel is a handsome Java Developer in Brisbane, Australia. Twitter: @danielalexiuc Daniel has posted 3 posts at DZone. View Full User Profile

Dependency Injection Makes Your Code Worse

10.25.2009
| 20818 views |
  • submit to reddit

"Dependency Injection" - you've probably heard and uttered this phrase so many times that it has become almost meaningless now. But just humour me for a moment. Say it slowly to yourself and imagine you are hearing this phrase for the first time.

It sounds insidious doesn't it?

If you went to the doctor and he told you he was going to give you a "dependency injection", then you would probably think there was something seriously wrong. If you were to buy a house, and the seller told you he wanted to inject a few more dependencies into the contract - would that sound good to you?

There is not much to like about either of those two words: "dependency" and "injection".

And it is the same thing with programming. Dependencies are not good, they are bad! They should be things that we try to avoid wherever possible. We spout principles like "loose coupling" and "high cohesion" to make people think that our code is structured and organised. But far from improving our code by being a way to structure and organise it, "dependency injection" actually makes it worse.

Questions worth considering

How can you possibly reason logically about what a method or class does when dependencies are being squirted in all over the place?

How could a system that facilitates the adding of dependencies to your classes possibly be beneficial? Especially when those dependencies are being managed by a "dependency injection framework" and you don't even know for sure what those dependencies will be?

A symptom of a larger problem

Most Java code I have seen (and written myself) is a gallimaufry of frameworks, patterns and objects that obscure meaningful code.

Dependency injection may have been developed as an attempt to solve some of these problems, but fundamentally it is adding to the problems. It is yet another framework to add to the tangled mess of code that allows you to abstract any real meaning further away and which enables your methods and classes to behave in more and more unpredictable ways.

My real gripe, though, is not with Dependency Injection. Dependency Injection is just a symptom (albeit a very obvious one) of the real problem facing Java programmers: the object-oriented paradigm.

Deep down you know it

There are other obvious symptoms that we are doing things the wrong way. Can you put your hand on your heart and honestly say that you are happy and productive with Dependency Management frameworks like Maven, and ORM frameworks like Hibernate? Or are they something that you spend way too many billable hours fiddling with?

The object-oriented paradigm has encouraged a generation of programmers (myself included) to write code in the most abstract, meaningless and side-effecting way possible. And even though we don't really use Java in an object-oriented way anymore (because deep down we know it just doesn't fundamentally make any sense), that same paradigm has taught us to write code that cannot be relied upon.

It cannot be relied upon because data is being twisted and untwisted into objects, those objects are being bombarded with dependencies, and those dependencies are recursively being infected by other dependencies.
Published at DZone with permission of its author, Daniel Alexiuc.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Tom Gardner replied on Sun, 2009/10/25 - 5:32pm

Dependency Injection (DI) can achieve beneficial results, but many other techniques can also be used to achieve the same benefits. DI is a very powerful technique when used in a disciplined way, but is subtly and lethally dangerous when used in an undisciplined way.

It is, as you correctly state, difficult to reason and predict software's function and performance if its operation can be invisibly altered by "code" in either XML or Java format.

Unfortunately the same forces that lead to DI being regarded as a useful technique are also the same forces that lead to DI being a dangerous technique. 

OTOH, I disagree that OO isn't useful and that people don't use Java in an OO way anymore. You "can write Fortran in any language" has been a truism for >30 years, but that doesn't mean you have to!

OO remains the best general purpose technique for creating large-scale software, but many other techniques have benefits in special domains (e.g. CLIPS/RETE languages for rule-based systems, FSMs for distributed communicating systems, etc, etc).

Use the right tool for the job. Use the right people for the job. 

No surprises there!

Jacek Furmankiewicz replied on Sun, 2009/10/25 - 5:33pm

Funny...I just finished a whole Spring based Java project and it looked just fine. Easily testable with mock objects too.

I think you've been hanging aroud some Clojure or Erlang mailing lists and drunk the anti-OOP cool-aid. There's some good therapies for that (try a detoxifying therapy of 30 days of Scala, that should do it).

 

Raphael Miranda replied on Sun, 2009/10/25 - 5:40pm

I think your analogies were *really* bad but I certainly understand your point.

DI is most often used with the intent of modularization, in the hope that if necessary in the future you can easly swap components.

Just as premature optimization is bad(most of the time anyway) premature modularizaion also ads unecessary complexity and overhead to your software.

In languages that better support functional paradigm, one has much more choice and tools to achieve modularization. In java however people are stuck thiking DI is a silver bullet maybe because of the inerent complexity of java framework stacks.

 

http://www.ibm.com/developerworks/library/j-fp.html

http://www.reddit.com/r/programming/comments/9pku9/mock_objects_and_dependency_injection_are_just/

 

Daniel Alexiuc replied on Sun, 2009/10/25 - 6:44pm in response to: Raphael Miranda

Hehe I was hoping to get a laugh more than anything with those analogies... Thanks for the links!

Garry replied on Sun, 2009/10/25 - 7:01pm

This article is certainly a laugh. Without modularity there are thousands of lines of perfectly understandable code that are rewritten and retested over and over again. Yes currently there are lot's of "wasted" billable hours spent tinkering trying to make these frameworks work. That's because some of the incumbent open source technologies (JBOSS specifically guilty) benefit from not having us understand because they want to sell support. Other well written frameworks encourage you to improve the framework so that the next million people won't have to tinker. Solve the problem, don't contribute to the problem!

Michael Riecken replied on Sun, 2009/10/25 - 7:53pm

Points for using "gallimaufry" in a sentence.

Daniel Alexiuc replied on Sun, 2009/10/25 - 9:12pm in response to: Garry

Vendors of Dependency Injection frameworks have had a lot of success trying to convince us that "Dependency Injection" is the best (or only) way to achieve modularity. It isn't.

I guess one of the points I was trying to make is that this problem cannot be "fixed" with a better or newer framework, because Dependency Injection is merely a way to try to "cope" with the nature of object oriented programming.

Andrew Arrigoni replied on Sun, 2009/10/25 - 9:35pm

Clearly the hammer is bad for carpentry. No carpenter should ever use hammers any more!

Karl Pagan replied on Sun, 2009/10/25 - 11:56pm

DI increases cohesion by removing any need to determine the direction of dependency and write any glue code.

DI reduces coupling by making all of your components modular (i.e. replacable) and have well-defined interfaces to each other.

DI and OOP are both more complex than the tighest solution requires. However each has their place and each can provide exceptional clarity to problems that can become a burden to implement without these techniques.

Andre Van Der Schyff replied on Mon, 2009/10/26 - 12:18am

"It cannot be relied upon because data is being twisted and untwisted into objects, those objects are being bombarded with dependencies, and those dependencies are recursively being infected by other dependencies."

What are you on about? If that's how you use Spring and Hibernate then I can see why you think it's inherently evil on some level, along with every other framework. Since when do you evaluate a framework based on the 'feeling' you get from the individual words, which in this case happens to be dependency and injection? Sorry, but you've completely missed the point.

Cosmin Mutu replied on Mon, 2009/10/26 - 2:49am

I worked with Spring Framework for some time and I find it very easy to map all dependency injections (or inversions of control) that I need. Of course, it takes a while while you split your xml files and while you make all the mappings, but after that it`s very very easy.

 If you`re new to the platform and if you don`t know what DI is all about then you will find yourself in the dark (since reading the code to understand what happens will not help you very much).

For some reason your following words really creep me out :

"And even though we don't really use Java in an object-oriented way anymore (because deep down we know it just doesn't fundamentally make any sense), that same paradigm has taught us to write code that cannot be relied upon."

If you really are doing this, then you should rethink if Java is the way to go for you.

 

 

 

Fab Mars replied on Mon, 2009/10/26 - 3:56am

I find it admirable that some people still dare to commit and express their views in a place filled with religious fundamentalists.

When I was younger, at the start of a project, I expressed my views and argued (whereas I knew nothing). Now I don't express anything unless I'm the one main architect, because I'm fed up using rhethoric to explain stuff learnt with experience, to clueless fundamentalists that won't attempt to understand and just want to have fun overengineering regardless of any project constraint...

What I want to say is that there is a whole range of usages for a given framework and that you ought to find the balance in your architecture between your project's needs and your interests at heart.

 

I have no prejudice or religion regarding software development; I coded in JEE before Spring existed, and I know a significant project can succed without DI (but with a lot of care and dedication). If I assess and believe my project needn't DI, we won't use it. This is more than rare now, though.

Overall I prefer DI over non-DI, because it removes the singletons and much spaghetti-plate-code.

 

So I can understand the point expressed here, and sometimes feel kind of the same :)

 

Olivier GERARDIN replied on Mon, 2009/10/26 - 4:19am

This article must be a joke.

DI does not create dependencies, it allows you to manage them in a more consistent, maintainable and testable way.

The dependencies lie in your objects. If they are badly written, then of course you will feel that a DI framework only adds to the complexity. Just a piece of advice there: law of Demeter. 

Dependency is a fact. There is no single object that can perform anything useful without relying on a bunch of other ones, whether you're conscious of it or not. Not using DI will not magically remove those dependencies.

In short: don't blame DI for weak design.

Yannick Menager replied on Mon, 2009/10/26 - 4:47am

As several people has mentioned before, this article is complete nonsense.

What you're complaining about is bad design, which has *nothing* to do with DI or OO.

Most technologies are double-edged swords... They have some use, and some pain in using them.

A developer must learn their strenghts of weaknesses, and use them where appropriate.

Jose Maria Arranz replied on Mon, 2009/10/26 - 4:51am

DI increases cohesion by removing any need to determine the direction of dependency and write any glue code.

False. The direction of dependencies is in XML form or as annotations, your dependencies are written as XML code and annotations. XML and annotations ARE source code.

DI reduces coupling by making all of your components modular (i.e. replacable) and have well-defined interfaces to each other.

False. You do not need a DI framework to build a modular code based on interfaces.

About replaceable: with a very simple .properties archive and Class.forName you can define wich classes can change. If ANY class of your code can be changed, Java is not for you, use an scripting language.  By the way: annotations cannot be changed without recompiling.

In my opinion there is one only reason for DI frameworks: boiler plate reduction. With a well done factory system you can do the same, more controlled and more predictable as your preferred DI framework, DI frameworks promise code reduction (XML and annotations are source code too). The problem is this boiler plate reduction is just real in very very simple cases (one instance-per class and similar), sometimes in the real world picking the appropriated service object is not as easy as mapping a class to a singleton object.

 

Tony Siciliani replied on Mon, 2009/10/26 - 5:04am

The problem DI originally addressed was service assembly, specifically, the separation of service configuration from service use. DI was considered a better alternative to Service Locator when writing frameworks, i.e. classes used by someone else, outside of your control.

Can DI be abused? Sure. Like anything else.  New techniques are proposed all the times to address problems we face. When used correctly they provide some advantage. When misused, they create more problems than they solve. Nothing DI-specific, just the story of our lives.

Michal Huniewicz replied on Mon, 2009/10/26 - 5:30am in response to: Jacek Furmankiewicz

Good idea, Jacek.

I would also recommend developing a project that someone would actually use, and together with other developers.

Karim Elsayed replied on Mon, 2009/10/26 - 5:40am

thumb up to Jose Maria Arranz !

Ronald Miura replied on Mon, 2009/10/26 - 6:22am

As said before, DI doesn't create dependencies. But it does make them explicit! Without it, your classes would probably have the same amount of dependencies, you just wouldn't know that.

That said, DI can be abused . It gets really worse when you use the same dependency injection mechanism for state injection (aka Seam and JSR-299), things may get really confusing.

Colin Rogers replied on Mon, 2009/10/26 - 6:32am

"How can you possibly reason logically about what a method or class does when dependencies are being squirted in all over the place?"

Easily - I know what the dependencies are, and which ones are injected - mostly because I can read their names and I can read code. Just like dependencies that aren't injected.

"How could a system that facilitates the adding of dependencies to your classes possibly be beneficial?"

The dependencies exist whether you inject them or not. In absence of a DI framework, those dependancies are *more* dependant... that is the whole point of DI framework.

"Especially when those dependencies are being managed by a "dependency injection framework" and you don't even know for sure what those dependencies will be?"

You do, if you configure the dependencies. They don't configure themselves.

"There are other obvious symptoms that we are doing things the wrong way. Can you put your hand on your heart and honestly say that you are happy and productive with Dependency Management frameworks like Maven, and ORM frameworks like Hibernate?"

*puts hand on heart* I LOVE hibernate. It's incredible the improvements it's made in term of my productivity. Same, but less so, with Maven. Modern programming is a breeze compared to a decade ago.

"Or are they something that you spend way too many billable hours fiddling with?"

Nope. Hibernate I spend bugger all time "fiddling" with. Maven had a bit of a step learning curve in the beginning, but after a while, you rarely need to spend any time on it "fiddling".

Nope that answers your questions. Personally, I think your post is bobbins. Sorry!

Colin Rogers replied on Mon, 2009/10/26 - 6:40am

Sorry - just want to add; When the crux of your argument is "It sounds insidious doesn't it?" - get a better opinion.

Harshal Vaidya replied on Mon, 2009/10/26 - 7:05am

One point which you raised makes a lot of sense. And that's about wasting a lot of billable hours with Hibernate. Despite having years of experience with Hibernate and numerous tools to automate all that hbm file creations and mapping object creations we continue to waste long long hours in tracking down many many excpetions which otherwise wouldn't have been a problem at all if we ended up using simple spring-jdbc.

 

Due to cost constraints companies cannot always afford Hibernate experts in their teams and hence end up hiring resources who have no or little experience with Hibernate. However, almost all of them have some or the other experience with a jdbc related framework, which completely reduces the learning curve. 

 I have strongly started not-recommending Hibernate where ever I can, unless dynamic caching is needed, where I think Hibernate is really good at. But then, caching can be used without hibernate also. 

Andre Parodi replied on Mon, 2009/10/26 - 7:08am

Dependencies are not good, they are bad! They should be things that we try to avoid wherever possible.
I agree that less dependencies is better. But DI just changes how you configure them. How does DI encourage dependencies?

Most Java code I have seen (and written myself) is a gallimaufry of frameworks, patterns and objects that obscure meaningful code.
I would have said most frameworks would actually allow you to eliminate boilerplate code which obscures meaningful code.

Veera Sundar replied on Mon, 2009/10/26 - 8:41am

I have worked in medium-big sized Spring projects. The Spring configuration files for the medium sized project were managble and readable. But when it comes to the big project, it took lots of time to manage the configuration file alone. And when more than one developers using the configuration file, it caused too many confusions.

Cosmin Mutu replied on Mon, 2009/10/26 - 9:15am in response to: Veera Sundar

It depends ....

You can split your configuration file into multiple files .. for example : name-servlet.xml can be broken down into multiple files like name-data.xml , name-service.xml, name-security.xml, name-servlet-config.xml, etc .. you can have as many xml files as you wish.. Of course if you only put configuration into name-servlet.xml it will become very cumbersome to read and understand.

As regarding to many developers using configuration file, well, that`s available for any kind of file and that`s why we have repositories. You synchronize your file with repository and you`re good to go.

Cheers!

David Lee replied on Mon, 2009/10/26 - 10:26am

I've been saying this for years.

The only place I've seen DI serve a valuable purpose is in frameworks like Tapestry and Grails.  

I'm yet to see an actual application that benefits from DI.  I'm sure they exists but, I'm convinced they are rare. I've asked various interviewees to name applications or situations where they could benefit from a DI framework and no one has been able to name one.

I get laughed at when I say, the time wasted on maven, spring and hibernate outweighs the benefits they provide.  But I've seen the same problems at several difference shops.  I call it framework madness.  I work with people you have simple crud apps that are 50mb war files.  It makes no sense.  

 

Great article.  

 

Guillaume Jeudy replied on Mon, 2009/10/26 - 12:02pm

why take a moronic looking picture in your user profile?

Jordan Zimmerman replied on Mon, 2009/10/26 - 12:23pm

I'll call your DI sucks and raise you 10: dependency-injection-makes-code-unintelligible

Henk De Boer replied on Mon, 2009/10/26 - 3:20pm in response to: Colin Rogers

How can you possibly reason logically about what a method or class does when dependencies are being squirted in all over the place?"
Easily - I know what the dependencies are, and which ones are injected - mostly because I can read their names and I can read code. Just like dependencies that aren't injected.

 

I agree with that, and in addition I know what the dependency's purpose is without knowing which particular implementation will be injected. Namely, I can see the INTERFACE said dependency is going to implement, and thereby I know its CONTRACT and by extension of that I thus know the PURPOSE.

When the code I'm inspecting is injected with a CustomerDAO, I know this object will allow me among others to retrieve... customers. I don't care in that code whether these customers come from the DB, a remote webservice, a mocked fix instance, an in-memory cache of some sort...

I just don't freakin' care! I don't want to care and I should not have to care!

It's pretty much the whole point of DI that I don't code in such a way that my code has knowledge about things it shouldn't have knowledge about and therefor becomes incredibly inflexible when needing to be used with other implementations.

Jordan Zimmerman replied on Mon, 2009/10/26 - 4:01pm

>I don't care in that code whether these customers come from the
>DB, a remote webservice, a mocked fix instance, an in-memory
>cache of some sort...

Oh, but you will care when you have to update the code someday. Remember your post when you're scratching your head in vain trying to figure out the actual instance of the interface that's being used and the original writers are long gone from the team.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.