On my last large project, I used dependency injection really heavily. I started out using constructor injection but even two or three dependencies resulted in really ugly code.
public MyClass(
IDependency1 dependency1,
IDependency2 dependency2
IDependency3 dependency3)
I am not a fan of property injection. Some people say it implies an “optional” dependency. I think what they mean is that there will be a default dependency (the production class) but it can be replaced with a mock object during test. Many times, my dependencies have dependencies, too, so I can’t provide a default value unless I used a singleton or something. My problem with property injection is that I prefer fully initialized objects and don’t want to accidentally forget to mock out a dependency during test.
So, I found a compromise. I created a “parameter object” that had properties for all of my dependencies. I passed these to my constructors. This had the benefit of keeping my code somewhat cleaner and I could ignore some dependencies during test if they weren’t touched.
Based on feedback I got the impression this was a bad idea. It was constructor injection or parameter injection – no compromise allowed. Later I realized that these parameter objects sometimes became their own classes (or set of classes).
That’s when I discovered an interesting pattern. Many business objects depended on other business objects, which had their own dependencies. What I ended up with was an interesting data structure, similar to a linked list.
This data structure could become fairly complex depending on the number of interacting classes. In most cases, the structure was closer to an n-ary tree. Each parameter object could link to any number of other objects (including other business objects). The business objects were the nodes of the tree and the parameter objects were like the edges connecting them.
I think connecting all these objects together without using a declarative dependency injection framework would be mind-numbing. The dependency injection framework I was using was going 8 levels deep in my code building the dependencies from the bottom up in the worst case.
The parameter objects usually just exposed the dependencies. On rare occasions, I would hide them behind friendly function calls and made them their own business objects (usually resulting yet another parameter object). I had to remind myself that the parameter objects only existed because I didn’t want to construct dependencies in the constructor (or pass them to the constructor). It only made sense to create new business objects when I started repeating myself. Even then, I ended up with an explosion of parameter objects.
I’ve read plenty of books explaining that this situation should never happen. Classes should have very few dependencies. It was a sign that my classes did “too much”. But in most of these cases, a business object used data from multiple database tables (repositories), configuration settings, services, etc. in order to calculate something. This occurred most often when implementing a series of steps making up a unit of work. When N things are needed to do a task, the best you can do is push those N things to other classes or on up the call stack. Is one class with 6 dependencies better or worse than 3 classes with two dependencies each?
I am hoping to get some feedback on this approach to dependency injection – in how it relates to architecting a business layer.
4
IMHO creation of “complete” classes via constructor has always been appealing, however setter injection requires a no-arg constructor, allowing pre-conditions (e.g. assertions) to be a reasonable alternative to guarantee “completeness” in the context of DI containers.
To me it is a trade-off between adding complexity versus implementing a simple, pragmatic, solution. And simplicity always wins.
To be perfectly honest, the intermediary “Parameter” classes seem like a bit of over-engineering here. You’re introducing code that deepens the object graph and actually hides the dependencies.
When using a container you can set up your environment so that whatever object you need is actually created by the container with all of it’s dependencies.
What I usually do is set up the infrastructure or framework so that whenever I’m in the actual application code, all my dependencies are already set.
I’ll set up my testing environment in the same way, so that there’s no way I’ll forget a dependency.
When using a framework like Asp.Net MVC, this means setting the framework up so that each controller is actually resolved by the container. The controllers here are the entry point to the application. Since the controllers will have dependencies to various repositories and services, the container will also resolve those and their dependencies, however deep the graph is.
This means that, if I’m careful not to blindly instantiate a service or repository I’ll always have objects which are completely ready to do their work, whether the dependencies are set via constructors or setters.
With some planning, the app layer (controllers/viewModels/views) and the business layer (repositories/services) can live within an infrastructure where you never have to instantiate a service using the new
operator, or even resolve it using the container (which is better, but if not used carefully can lead to problems, where you introduce unnecessary dependencies to the container itself).
About setter vs constructor injection, I disagree that setter injection implies optional dependencies. They are dependencies just like the rest, and are very useful when you have a hierarchy of classes in which constructor injection would mean dragging parameters through multiple levels of constructors until finally setting the dependency in some base class. Of course, they have their trade-offs, specifically, that with setter injection, you have to be careful with your constructor logic, which IMO, should be kept to a minimum, outside of setting up the object.
7