Until this past week, I have very little experience with dependency injection containers like Spring. My dabbling in Grails had been my most extensive work using a DI container. I just used it at that point, without giving it much thought. I was more focused on learning Groovy and figuring out what Grails offered me as a web application developer. This lack of experience changed last week when my team at Mentor Graphics learned we are inheriting a web application from one of our contractor teams. The project is another Google Web Toolkit application like the one I have been previously involved in writing. This new one differs in there is a lot more server-side application code. I quickly discovered the team has used Spring’s dependency injection extensively. Although dependency injection is certainly old news to most folks, I found it interesting enough to inspire this blog post.
First I’d like to sum up my working definition of dependency injection, based on Martin Fowler’s description from nearly 10 years ago. Dependency injection is a pattern where a class which depends on another object (often called a “bean”) is provided an instance of the dependency as opposed to self-instantiating it. Typically the dependency is typed as an interface. Hence the dependency is fully decoupled from the concrete class by neither referencing it nor calling its constructor (a little more on this later).
Containers aside, this is a pattern I was already using quite recently due to our refactor to utilize the Model-View-Presenter pattern. In this pattern, the presenter interacts with the view via an interface. The presenter then has a view as one of its constructor arguments. It has no idea about the instantiation of the view. This allows me to provide the real view with GWT widgets in production mode, or mocked views in test mode.
A DI container takes it to the next level in that I no longer need to instantiate the dependency at all. Rather than writing my own assembler, the DI container provides this functionality. In the case of Spring, this is accomplished via XML files (which is unfortunate because I find XML annoying). Hence any class which depends on some injectable interface will be given the implementation configured in the XML. In the case where the interface has only one instantiable implementation, there is no need for the XML configuration. Spring is kind enough to make the only available selection for you.
As Fowler points out in his aforementioned blog post, dependency injection can take on several forms. The three forms he mentions (constructor, setter, and interface) do not break encapsulation. I suppose with some of the voodoo available in the JVM, Spring doesn’t need a public accessor to inject the dependency. All one needs to do is declare a
private field annotated with
@Inject. Spring will break the scoped encapsulation of that field and set it. I have mixed feelings about this approach. I like how it requires minimal code (just a declaration). On the other hand, I can’t (easily) write code to set those fields myself if ever needed. I’m stuck with my code only working in a dependency injection container. This isn’t a huge deal, but I always get a little hesitant when my code is coupled to a container of some sort since it limits my options on how I can run and test it.
Speaking of testing, DI is a great way to facilitate unit testing, regardless if you utilize a DI container. This was the primary motivation behind my adoption of the MVP pattern. The view is handed to the presenter at construction time, allowing us to hand over a mock view for unit testing. As with most testing disciplines, I would argue this leads to a better way to organize the code by separating concerns.
One thing I really like about the DI approach is that it allows objects/beans to be dependent solely upon interfaces. The practice of programming by contract always breaks down in Java at the first line of the dependency… you have to instantiate a concrete class which is not definable via an interface, causing a direct coupling to the very thing you were trying to not couple to! Of course, we have long mitigated this by creating factories. And by “mitigate” I mean, we just moved the problem from here to there. You still have to instantiate the factory, or couple to its statically-defined methods.
As I was browsing around this new project, I also noticed that it was common to be injected with a bean that itself had several injections. This is where I see a big win for DI because constructing the dependency for yourself would require you to know a lot of details about that dependency. You have to know the transitive dependencies of everything you need. I think this is even more important than my previous observation regarding avoiding a coupling to the concrete classes via constructors. Without the transitive dependency resolution, this code could have gotten messy quickly.
If there was one thing I could change, it would be to create beans without an interface (and perhaps this is in fact possible but I’ve not spent the time to confirm). Now this may sound counter-intuitive at first because it seems to defeat the whole purpose of decoupling from the implementation details. While that is good, it has an unfortunate side-effect of violating DRY. I’ve observed that there are plenty of interfaces written which have precisely one instantiation. This means that the public methods have to be defined in an interface and repeated in the implementation. From the look of the formatting of the interfaces, I’m pretty sure that they always wrote the class first and extracted the interface with Eclipse. While that certainly eliminated the labor of writing it twice, it’s still written twice. There’s still twice as much code to maintain. In general I don’t like this approach of creating an interface unless you think it is likely that you will actually have more than one instantiation of it. Of course, if we throw in mocks for testing, then we DO in fact have multiple instantiations for each bean. While this should be sufficient for my complaint, I’m still a little reluctant. I’m used to using JMockIt which can mock ANYTHING.
I am definitely looking forward to getting more familiar with Spring on this project. I’ve long been intrigued by that disruptive force in Java. Dependency injection looks very promising for eliminating a lot of pain in developing complex applications. It should be a lot of fun, and perhaps inspire some more old-news blog posts. Maybe I’ll even get around to learning the cake pattern in Scala so I can make comparisons to DI.