The One Correct Way to do Dependency Injection
A couple of weeks ago a coworker told me that they have a little utility in their projects in order to set private fields for tests. He kind of claimed they needed that since they are using Spring, which in production sets the dependency. I was a little confused. But after looking into it I realized that there is an (anti)pattern going on that needs some fighting against. Lets have a look at the pattern.
Spring (and other DI frameworks) can inject dependencies into private fields. It looks like people like to use this because it combines some compelling properties:
- Very little boilerplate code. All you need is a simple annotation on the field.
- Since the field is private nobody outside the class can change it.
But now when you want to test your class and want to assign e.g. a mock to the field you have to either setup a Spring context in your tests or use reflection in order to access the field (just as Spring does).
Now something is really starting to smell bad here. One of the purposes of Dependency Injection is to decouple code, which in turn should make the code easier to test. Now that didn’t work out to well.
So how can we clean up this mess? We can write a setter for the field. That solves the testing problem. It adds a little boiler plate code, but hey we are talking Java here, so you should be used to that. But now we have a setter which anybody can call at any time. At the very best that doesn’t make any sense at all in the production environment. In the worst case somebody actually uses it and creates some ugly bug.
So what do you do when you don’t want anybody to change a field? Correct you make it final. Great, now you have a compile time error in the setter.You can only set a final field in a constructor. This leads naturally to the solution of all our problems (and possibly to world peace): Make your dependency a constructor argument!
This is the only place where dependencies really belong. If you try to stick to that rule I’d expect you’ll encounter the following two problems.
- You’ll find classes with lots and lots of constructor arguments. I’ll bet that class does a lot of different things and really needs to get broken down into smaller pieces.
- You’ll find cases where a class A needs an instance of B and B needs an instance of A. This is a typical case of a circular dependency and is obviously bad. In my experience the solution is either to make B a part of A when the two are so strongly dependent that they really should be one class. More often though there is at least one more class C hiding in there so that B doesn’t need A but only C.
So really the problems you’ll find when doing constructor based dependency injection are problems that are present in your current code already. So don’t shoot the messenger, but fix the problems in your code and go for constructor arguments for dependency injection.






I don´t agree with you on the first problem: lots of ctor arguments need not be a sign of multiple responsibilities. In fact it can be a sign of exactly 1 responsibility. And I´d even argue this should be the only reason for a ctor dependency argument:
An object depending on others should have as its responsibility only “integration”, i.e. wiring together its dependencies to form a whole.
If that´s really the only responsibility of an object then it´s only dependent on the syntax/form of the injected objects. It does not have a clue as to what they are doing. Therefore it´s no problem to be dependent on many objects. Like a DI container is dependent on many objects.
(This is a more roundabout statement than what I really mean. But I leave it at that to make it a bit more thought provoking
@Ralf If the task of the object is to provide other objects with dependencies, shouldn’t it instantiate those objects?
Anyway: You are correct that there are a few (possibly one) good reason for lots of constructor arguments. But I still think most of the time it will be the reason layed out in the article.
I agree with using constructor injection wherever possible and was mostly influenced to use it by the teachings of Misko Hevery: http://misko.hevery.com/2008/11/11/clean-code-talks-dependency-injection/
What usually bugs me is, that when using the Spring XML configuration you can only express the constructor arguments as ordered list instead of expressing them as named properties. Constructor dependencies become much nicer to use when using annotations (Spring or Guice) to express the binding, but that is a whole other discussion in itself.
In a perfect world you should not have any object instantiation in your business logic and have the DI layer create and inject those dependencies. The only exception are pure data objects (Holders, DTOs,..) which you still have to instantiate in your code.
Thanks for this great let`s-think-this-through-article! One of the most pressing design problems in my current project actually is another verbalization of solution 1. Interesting how two seemingly unrelated problems are just the very same thing.
If you were there in mid 2003, this was called type-3 IoC by PicoContainer. Hardly any news though.
The more I think about it, the less the whole IoC/DI feels like a valid object oriented approach to me.. This leads back to good old structured programming of the 80′s on a straight wide road.
I certainly don’t claim that Constructor Dependency Injection is anything new. Also the insight/opinion that one really should use only constructors for dependency injection isn’t new. I think Codemonkeyism tweeted just that a couple of weeks ago.
I do think DI is a good idea. I don’t understand why I need a framework for it though (well I do understand but I don’t like the reasons).
For the question if OO is a good idea at all … I leave that to people way smarter then me.
What I dislike in DI is exactly the “background magic” you start the post with, and the massive horde of singletons which usually come with it. The cake pattern (Scala) was a very surprising approach on the first look but now I think it’s actually a better idea than a DI framework (or manual DI, though it’s a kind of manual DI at the end).
Now that you mention whether OO is a good idea at all.. excellent question. The more I learn the very basics of Haskell, the more I actually question that too..
This path of learning reflects a kind of personal evolution though, so I consider this “time wasted well”. I really wonder where it ends.
If only EJB 3.0 allowed constructor injection…
Have you never seen the Static Builder Pattern from the Second Edition of Josh Bloch’s Effective Java? Better solution than your two listed here.
I agree with your conclusions though.
To conclude that shortcomings of a DI framework proves that object oriented programming is wrong and we should back the car up and do structured programming would be like finding out that fake food coloring was carcinogenic and therefore, people should stop eating ice cream. Structured Programming collapsed because it didn’t work in larger projects. If you are making toys, by all means, just use SP.
@Rob: So, does OOP work? And then which kind of OOP? The 1988 kind of OOP or the 1995 kind of OOP or the 2003 kind of OOP?
Obviously OOP has not been able to deliver on reuse as expected. And also obviously OOP has not saved us from heaps of technical debt and brownfield code.
So what exactly is good and worth to keep in OOP, what needs improvement, what needs to be shed?
@Raf – Your statements make me want to respond with my own socratic riddles, or sophistic.
So reuse was the promise which, when not delivered, determines OOP’s terminal state? I would argue that objects have delivered on reuse. But reuse is still too much work. Properly done libraries are so much easier to drop into a project and start using than would be comparable code from a procedural project. Did you ever do Windows programming? A treatise in the disintegration of SP: all functions take 5-10 params, a couple are structs with a ton of members. Especially intelligent use of chaining builders makes it incredibly easy to drop components in and start using them (via DSL).
As to the various versions, I think that objects are far from perfect, and I personally believe the future will eventually be more agent-based, which is basically object-oriented, but has different more interesting answers to plasticity, collaboration, etc. We’ll have to see. I welcome those who are doing small things going back to SP. Problem is, any project that has an ounce of interest will soon make those environs seem like quite a small cage.
@Rob: Objects have not done much above ordinary libraries in terms of reuse, I´d say. We were able to encapsulate code in DLLs and linker modules before OOP. In fact the much acclaimed VBX libraries which did so much for UI components back in the 1990s were just DLLs with a non-OOP interface (if I remember correctly).
And DSLs… I doubt we´ll see much use of them above SQL and RegEx. People have a hard time to come up with decend libraries/frameworks. How should they be able to sling their own DSL?
It would need a very generic DSL to find widespread use. A DSL to help with very fundamental stuff – which then probably would replace some of what OOP tried to deliver on so far.
A DSL for integrating functionality maybe. I´d be all for it
Confine OOP 3GL code to small units which then are connected using a DSL.
We clearly live in different worlds. The DLL components of the 90s?? You mean the age of Alan Cooper and VB Uber Alles? Please. Pathetic march of the tinker toys that went down to a bitter defeat (not the conquest they and their very rich backer predicted).
Most people who argue against objects use anecdotal evidence that generally translates to ‘I am happier when I don’t have to deal with the complicated world of OO.’ I like to make decisions based on more data, e.g. metrics. Metrics have shown that SP runs out of gas at around 100K lines of code. Maybe you are a super user who is going to go and do what no one else has done because you are so great at designing your procedures. I have more interesting things to do than imagine such silly high wire acts. Again, SP runs out of gas for a simple reason: the context, as it gets more complex, having to be passed around all the time, becomes toxic and then quickly terminal.
As to DSLs, that was why I said we are clearly traveling in different worlds. Every single thing I am seeing in the Java world now has one. The new versions of Hibernate Core and Search, Joda, Guava, etc. A DSL is not some scary thing that makes it harder for the user to figure out. It’s the opposite. The user constructs an object, chains some calls, and gets their product. (Interestingly, objective c has pretty much the same thing with its named arguments, or labeled arguments in the function signatures.)
DSLs don’t replace oop. They solve the stupid part of OOP, which is that you have to construct the object, then set a bunch of things on it, then hope you set all the things it wanted, and try and finally use it. If you use the Static Builder, you chain the calls and then build the object. The builder can validate whether you have provided what is required.
Learn something about the state of the art of a language/programming paradigm before you personally proclaim its death.
@Rob: It´s sad you need to become personal and ask me to first learn something.
That´s especially sad since you yourself claim to know the truth. All´s well. DSL are about to solve our problems. We´re almost there. And on top: whatever happened in the 90s was bullshit.
On top: I just said that OOP did not deliver on reuse as much as it promised. Reuse through libraries is decades older. We never needed OOP for that. Modula delivered on reuse possibility as much as C++ did.
And I really doubt that OOP´s promise to make reuse easy through inheritance did a lot of good. How else do you explain the GoF statement in their 1995 (!) book: favor composition over inheritance?
As for anecdotal evidence: I´m doing team assessments on a regular basis, meaning around once a month. This means every month I see a different (!) team and ask them to solve a simple problem using their choice of tools and paradigms – which today means they use Java/C# and Eclipse/IntelliJ/VS.
And guess what: Those teams fail to deliver 90% of the times. They fail to deliver on time (which means within a timeframe of 2h). They fail to deliver on quality (which means their code looks like s***).
How come if all´s well in OOP land? Are those guys just dumb programmers? Well, let me tell you, they are – as you might expect – average.
Yes, this is not really an empiric study I´m talking about. But certainly it´s more than just anecdotal evidence given by people about themselves. I´m outside those teams, I don´t have stakes in their performance. So my point of view is pretty neutral. It´s diverse teams from all all kinds of business domains. It´s self taught programmers as well as guys with bachelor and masters degrees. They´re trying to make sense of OOP, patterns, principles, practices. So what I´m seeing is not state of the art, but state of the practice.
My conclusion for such pretty broad sampling: OOP does not deliver in a lot of ways. Things become better. DSLs might help. Fluent interfaces might help. But the very basic paradigm is making it hard for teams to deliver functionality and (!) evolovability. There´s work to do.
So maybe you want to sit down and do your homework and gather some data yourself instead of just reading blogs and stuff from people who are above average and highly motivated.
Oh, no, it’s the victim defense. I asked you to learn something because you did an original post that showed you have not even read Effective Java, the accepted bible of Java programming. I was polite in that round, but when you kept pressing your ‘OOP is dead, and never delivered anything,’ I noted that you are declaring it dead from behind the bus. Show me some code you have written recently in Java. I’ll show you some of mine. I am not the one running around declaring an Era of Computer Programming failed and over, you are.
I have blogged endlessly on the shortcomings of various programming approaches, so your characterization of me as a glad-hander who is telling people we are almost there is laughably wrong. I am saying that between the two choices (false ones) you have laid out, it’s not even close. Would be like saying ‘cars pollute, therefore we should go back to the horse.’ I am saying, no, the horse is not the answer.
What does SP say about models? They are already handled by the db, right? Like, make an ER diagram and then just push your strings around with your procedural goo? Wow, sounds exciting! I want richer modeling semantics. Programming without serious models is a complete joke. SP basically says ‘pass me what I need, I’ll give you back what you want.’ Which is not a way to model something large and complex.
I agree with some of what you say about average programmers not being able to do objects. It’s not because OO didn’t deliver, like it’s some kind of lying political candidate. I have worked with a lot of average programmers, and I have trained a lot of programmers. You know what I have found? Old dogs rarely learn new tricks. But I have found that people can be taught objects and patterns. Let’s not leave out the fact that edu has been a completely miserable failure. I just hired a guy a year ago who was literally a week out of a CS program at one of the richest colleges in the US. I wanted to hire a lawyer and sue the teachers who took his parents’ money. I don’t know what they thought they taught him, but it was a joke.
Procedural Programming is like the end of Nietzsche’s Zarathustra: the frustrated followers who’ve been told to find their own way instead return to their prior idols. Sad.
@Ralf, wow, your conclusions are all wrong. I said whatever happened in the 90s was bullshit? No, I said VB and its DLL components failed to deliver (do those words sound familiar?). Lot of great stuff happened in the 90s. Half the 90s was the rise of Java. So try and control your very obvious inclination to paint every thing in only black and white.
As to the Gang of Four, what on earth is your point there. Notice the word choice there: FAVOR!! Something you cannot understand because you only like yes or no. Favor means use this when possible, otherwise use the other. Again, I just find this constant ‘I did inheritance once and it made a mess,’ baby talk. There are a lot of places where inheritance makes a lot of sense.
Did you happen to notice that tons of the DPs in Gang of Four use inheritance? Like builder with its Abstract and Concerte builders and Bridge with it’s 2 hierarchies (bound by a delegate)? Composite, Factory Method.. on and on….
Rob, please choose one of the following final replies from me:
a. You are right. I apologize for speaking up without knowing the basics. I´ll go back to school and learn. The resources you´re putting online sure will help me with that. Thank you for showing me the light.
b. This discussion has become too meta and too personal for my taste. Sorry for having enraged you.
c. I´m out of here. You don´t get what I mean. You are not interested in questioning what you deem the holy grail. This becomes tedious and boring for me. Good luck with your students and suing some university.
d. We´re having too many misunderstandings to resolve here. We should invest our time differently. Thank you for yours.
Clearly your therapist has not helped much on your control issues.
Here’s my answer: e. it’s amusing. So you mock me for being outraged that a student who paid $150K doesn’t know basic things while you issue a decree that objects ought be abandoned because they are a tissue of lies. Ok, that makes sense. Kind of like ‘no one trained him on how to speak english then we dropped him into coursework where it was required and he did poorly. Time to abandon english.’
Maybe you would prefer to continue with a puppet where you can provide both voices.
I did notice that you didn’t address any of the issues I brought up with your theses, e.g. that the Go4 patterns are soaked in the bogie man inheritance. It’s ok, there are no good responses to contradictory facts.
I didn’t say you were clueless. You seem very educated, though, in a glowing dream of yesteryear. I just said go try some of the newer approaches before you conclude that there is no way to save objects.
You forgot all of the above. Clearly that is your response. I am not enraged. You are. You just think the veneer of politesse you are trying to coat your material with masks that. It doesn’t. (P/A)
To bring back the discussion to Jens’ original topic: the post pretty much summarizes most of my arguments for constructor and against field injection. However, there’s a few things I’d like to add:
1) Dependencies need to be communicated publically
Field injection completely bypasses that. Take a look at the JavaDoc of the class or type new MyComponent( + CTRL+SPACE. Nothing happens. You’re actually forced to look into the implementation code to see what fields you have to inject. But “inject” by what means? Reflection? Awesome…
Exactly the opposite for constructor arguments: constructors are listed in JavaDocs, can be documented and are immediately available to code completion. Beyond that you can actually have assertions in the constructor that prevent someone from handing in nulls for mandatory dependencies making sure *the object is always in a valid state once constructed*. Especially this part is what makes constructor injection so valuable to me. No ugly null checks sprinkled around the code or even potential NullPointerExceptions someone accidentally forgot to setup the instance correctly
2) Setter injection for optional dependencies
I think there’s one exception to the guideline to use constructor injection: optional dependencies. In case a class in either reasonably work without a given dependency or might gracefully default it to something one might provide a setter to allow customization of the instance. Following this approach you discoverably and cleanly communicate bot mandatory and optional dependencies of a class.
@Ralph – IMO a factory is a completely different scenario as it’s responsible for creating the object instances. So you’re arguing a class could have the responsibility to simply collect various instances of various types and do what? If it purely delegates, why have the class in the first place? Usually those classes add some value add over the plain dependency instances (e.g. having some kind of ordered access to multiple implementations of a lookup interface). This might be an exception to the general rule but I’d argue that in 80% of the cases developers tend to equip their classes with too many dependencies and then argue against constructor injection as it makes this flaw obvious.
@Florian – Spring’s XML element does not have to be listed in order. If you have distinctly typed constructor arguments the order actually doesn’t matter at all as Spring will assign the referenced beans by type. Beyond that you can use the “name” attribute to make the parameter binding explicit (similarly to ) but will have to compile with debug flag then.
@Oliver: I´m not talking about a factory. If a DI container functions like a factory then that´s fine with me. And I´m all for ctor injection.
However, I´m asking: What´s going on if a dependency tree looks like this:
DomainlogicRootClass DomainlogicClassA DomainlogicClassF DomainlogicClassB DomainlogicClassK DomainlogicClassLOn every level of this hierarchy domain logic resides. That´s how it´s usually done. That´s why IoC is used and a DI container is supposed to inject an instance of DomainlogicClassF into an instance of DomainlogicClassA etc. That´s what Jens ment, right?
Now, what I find highly problematic is that domain logic is spread vertically (!) over the hierarchy. That not only makes all non-leaf classes hard to test. It also violates the Single Responsibility Principle (SRP).
The purpose of all non-leaf classes is twofold: they are responsible for executing domain logic plus (!) they integrate lower level functionality.
This sure sounds normal, even inevitable. But at least inevitable it is not.
So what I´m saying is: If you´re serious about SOLID, then take SRP seriously, which means become eXtreme in comparison to its usual interpretation, do xSRP
Keep all non-leaf classes free of domain logic (or whatever concern we´re talking about). Do not let them add value in terms of fulfilling functional/non-functional requirements. No expressions, no control statements.
This will degenerate those classes. They´ll become pure integrators. But that´s ok. No, that´s even highly beneficial, I´d say.
Firstly, this makes all classes much easier to test. The need for mock objects is drastically reduced. I haven´t used a mock framework in months for my development.
Secondly, this makes it very easy to spot where functionality you need to change is located. It can only sit in one of the leaf classes.
Thirdly, all non-leaf classes become dispensable
Since they don´t fulfill any function above integrating lower level objects into a whole, this can be done in a different and easier way. Think DSL if you like
I´ve been working along these lines for the past 2 years. And is has greatly simplyfied my coding. And it has much improved the readability of my programs.
PS: Just to anticipate a usual objection: I´m not talking about your grandfather´s procedural or structured programming (SP) here
This is different at least in that SP never was that rigorous in terms of SP. Also this approach does not require you to give up on ADTs or encapsulation. Technical OOP is just fine – but it´s curbed.
This sounds interesting, yet I don’t see how it works. Lets considere a trivial example:
Class A chooses on some condition to delegate to b of type B or c of type C
How would you move the responsibility of A (deciding which delegate to use) into a leave class?
@Jens: You see, that´s the point: A should not decide. A decision is part of the domain to which A belongs.
If you want to follow the SRP you have to choose:
-either A integrates B and C functionality
-or A contains business logic.
Or at least this decision has to be made for each method:
-either a method a of A integrates b and c
-or a implements domain logic – and the decision has to be made somewhere else.
@Ralf I do see your point (which of course doesn’t mean I agree)
But I don’t understand how I can write code where only the leave nodes contain logic. Hence the example with three pieces of logic
A: decide between doing b or c
B: doing b
C: doing c
I’d implement it more or less like this:
class A(b:B, c:D){ doSomething(){ if (some condition) b.doSomething() else c.doSomething() } }How would this look after transformation into a form where only leave classes contain logic?
@Jens: Pushing the logic into the leaves requires you to use continuations, e.g.
class A { B b; C c; ... doSomething() { decide( b.doSomething, c.doSomething); } decide(Action onTrue, Action onFalse) { if (some condition) onTrue(); else onFalse(); } }This works fine in C# where Action is defined as
delegate void Action();
It´s a type safe function pointer.
See how doSomething() now only does the “wiring”? It is independent of the condition and also independent of how the decision is made, whether an if is used of some other means. As long as the basic structure of the decision (no input, two alternate paths to follow) stays the same, decide() does not need to change.
SLA just would push “some condition” into a function of its own. But this goes a step further. If even pushes down the decision itself. decide() is just a method with two out-flows. maybe they alternatively carry data. maybe under some circumstances processing continues down both paths. decide() does not care.
I see where you are heading … not convinced, but at least, where you are heading.
What would it take to convince you?
I guess: You need to see this applied to a larger code base.
And you need to experience the development process using this approach. Because that´s changing the way you approach solutions.
exactly
What do you do when you want to communicate between a View and it’s Controller/Producer? In that case you need the view injected in the presenter and otherwise.
@Dan In case of a circular dependency you are right, one has to get injected with a setter. BUT this isn’t a real dependency in the sense that it should work perfectly well without that dependency. Or to put it differently: it is just a listener/oberserver.
A distinction I failed to make in the article
With CDI/Weld you can inject the View in the Controller and otherwise without getting a cyclic dependency when you “lazy inject” at one side (http://stackoverflow.com/questions/8749073/better-way-to-pass-class-reference-to-an-injected-instance?answertab=active#tab-top)
If you do field injection you can wire almost anything to anything. That doesn’t mean it’s a good idea. Just because the container doesn’t bark at you, it doesn’t mean nothing is wrong.
Field injection actually subverts a crucial part of the whole DI story: exposing dependencies. With FI you still cannot reason about the dependencies of a class just by looking at it’s public interface (aka. JavaDoc, not a Java interface). With constructor/sett injection you actually do. So while the latter two impose a slight overhead in initial coding they actually serve an important purpose from an architectural or design perspective.
Especially constructor injection actually prevents you from introducing cyclic dependencies. If you do introduce them you essentially make the two parties one because you cannot really change the one without risking to break the other, which in every case is a design smell. It still can be reasonable to do this (as your example introduces an interface to decrease the coupling) but you’re still left with quite a few issues. How do you reasonably test the instances in isolation? How do you set the dependencies in a unit test at all? Reflection? So you’re writing the first client for your code and already work around drawbacks of your design?
Actually I’ve already discussed this in length in this comment: http://blog.schauderhaft.de/2012/01/01/the-one-correct-way-to-do-dependency-injection/comment-page-1/#comment-4765
Cheers,
Ollie
Hi Sebastian,
What about doing field injection and making the fields package private? In that case you have to place your tests in the same package but can than access its fields from there and put your mocks in it without the use of any other tools or franeworks?!
No it is not ok.
1. The field has package access, but there is nothing in the package that should need to access it.
2. The field is not final, suggesting it is ok to change it to some new value during the lifetime of the object, which it probably isn’t
3. There you gave no reason why you don’t want to use constructor injection in the first place. Try to formulate the reason why you don’t want to do that, then look me in the face and tell me it is not a design smell in itself.
Season’s Greetings and a Happy End of the World.
After surviving the armageddon I want to reply to that again.
The whole idea came from Adam Bien because of the pragmatism of field injection http://www.adam-bien.com/roller/abien/entry/inject_with_package_private_fields . But as you can see I’m not sure about it and because of that I found your blog. Thing is that it is obviously less code to write but not at last I’m loosing some comfort when I write unit-tests as I can see all my dependencies at instantiation time when they are in the constructor and the test turns red immediately when I add a dependency in the class under test which is not necessarily the case with field injection.
Hi Tim,
congrats for being one of the survivors of the apocalypse.
I think you wrapped it quite nicely. With package scope fields, you get a little less code and less hassle during testing.
With constructor injection you get expressive ‘correct’ semantics.
In the end it is your decision.
For me the testing hassle is a benefit as I can see instantly which tests I have to look after.
Thanks for your opinion on that. Appreciate it much