Today is one of those days where I either react to short tempered or don’t get my point across:
Did attribute injection for years? Try to change to constructor based injection and have the circular dependencies slapped into your face…
— Michael Simons (@rotnroll666) June 13, 2016
This is what I’m experiencing those days, with some projects at work and also with Daily Fratze those days.
In younger (more current) projects I took really great care to avoid setter or attribute based dependency injection. You can do completely without – at least in a Spring based environment, where you can use an injectable entity manager as well.
There are enough blog posts out there that emphasize the advantages for testing, having only “complete” and ready to use instances in you hands and so on, but the above point is one of my personal main advantages.
When I first came across a real dependency injection framework nearly a decade ago I was like “wow, this is awesome!” and had suddenly
@Inject) at nearly every attribute and managed to create “god classes” in no time. At the beginning I still generated getters and setters as well… Not being aware, that the fields would be set via reflection anyway (removing them showed one flaw: How to test stuff without firing up the whole thing?).
Anyway, the “god classes”: Big piles of mud having a dozen collaborators or more and doing “everything”.
I’m not sure how that looks today with junior developers… Do they learn that stuff in university? Or is this temptation still real?
If you use constructor based injection you immediately get two advantages:
- The pain of having a constructor with a dozen parameters, knowing that your thing *will* have too much responsibility.
- A slap by your DI framework if you have circular dependencies.
Why use yet another tool in your build process to point out your obvious code smells when start up fails? If you really have to have that circle, there are ways (for example having a setter for that one dependency but than the “problem” is obvious and at last or framework dependent solutions).
Last but not least: You get dependency injection done right in my eyes, which is: no obvious need for a DI framework. You can construct and use your objects “by hand”, if you want to. That is especially true for the latest Spring Framework release 4.3, you can even omit the
@Autowired on a unique, non default constructor.
The current problem I fixed today was like this: I have to create to entities that might depend on each other. For both creations I used a separate service and both services where directly accessing an entity manager and both where depending on each other (the one using the other for creating an instance, the other using the first for accessing stuff from the other entity). By introducing a data access layer in form of a Spring Data repository both could easily be decoupled. By further taking care that if a relationship between the two instances of the entities exist, the entities can only be instantiated completely (that is, fully populated, valid and ready to be persisted), I solved the circular dependency, got rid of an unnecessary BeanValidator in a service (I had to use a command object to call the other one) and remove somewhat along 40 lines of code.