Book Excerpt and Interview: Dependency Injection
Dependency Injection by Dhanji R. Prasanna is a book that tries to explore the DI idiom in detail, and present techniques in Spring and Guice. Dhanji is a Google software engineer who works on Google Wave and also contributes to Guice, MVEL, and other open source projects.
The book is divided into 11 chapters.
- Chapters 1-4 provide an introduction to testability and the reasons for using dependency injection, its various design patterns, and usage idioms, particularly how to choose these patterns and apply them in various situations.
- Chapters 5-6 focus on scopes, which, are a way of managing state without polluting logic with infrastructure concerns. They also explore problems with common idioms such as the static singleton anti-pattern and solutions using dependency injection, and examine scopes for web applications and other purposes.
- Chapter 7 talks about how to manage the application’s lifecycle via the dependency injector. This involves sending objects notifications of important events in the life of the application and designing custom lifecycle infrastructure.
- Chapter 8 deals with aspect oriented programming (AOP) as it applies to dependency injection, how it aims to save on boilerplate code, and reduce the risk of errors. A large part of this chapter is devoted to potential problems and pitfalls in using this powerful technique.
- Chapters 9-11 investigate concurrency and design and look at case studies in performance, design, and design integration with third party frameworks. Chapter 11 is a case study on how to build a complete web application using the concepts presented throughout the book.
Also there are two appendixes that discuss alternate approaches to dependency injection frameworks, SmartyPantsIOC for Flex and the Butterfly Container.
The book’s publisher, Manning, made an expert available to InfoQ which includes the contents of the 3rd Chapter entitled ‘Investigating DI’.
InfoQ had a Q&A with the author about his new book:
InfoQ: Hi Dhanji, would you like to tell us a little bit about yourself and how you came about writing a book about DI?
Dhanji: Sure. I am a Software Engineer at Google, in my day job I work on Google Wave and in my spare time I contribute to Google Guice and the MVEL expression language for Java. I also represent Google on the Servlet and JAX-RS expert groups.
I was initially approached by another publisher to do a small Guice book. At that time, my good friend (and Apache Wicket developer) Eelco Hillenius was writing Wicket in Action for Manning. He got me talking with them and they suggested a much more comprehensive design patterns and SW engineering book, which appealed a lot more to me. I was also happier to do a book that was not biased to any one framework.
InfoQ: What is "Dependency Injection" and what is the problem that it tries to solve?
Dhanji: Put very simply, dependency injection is the idea that instead of going out and finding all the things you need, you as a service, let them come to you. At the core, the pattern simply refers to decoupling a service from other services that it depends on, so that those dependencies may be replaced with mocks for testing or variants for other environments as appropriate. By remaining agnostic to its dependencies, a service is focused, clutter-free and is able to evolve easily, all while adhering to a well-defined contract.
In the book I explore various design patterns that relate to DI and that may be used for application architecture in general. Frameworks also bring a lot of enhancements to everyday programming that the pattern alone does not provide. So a thorough examination of DI, in the context of this book, is really an examination of application architecture and design in a broad sense. I hope the book's subtitle (design patterns) conveys that.
InfoQ: On chapter 9 you support that "best practices portended by a language and its engineering fundamentals are the same as those proffered by dependency injection". Since this is something that confuses both new and experienced DI users, would you like to elaborate on it?
Dhanji: This is pretty similar to the point I made just earlier--that is, this book is really about good application design and architecture. Engineering fundamentals such as type rigor, loose-coupling, modular design and component reuse are the same basics that DI technologies encourage and disseminate. Though, in a slightly more organized form with the use of declarative APIs.
Consequently, mistakes made when designing with DI are the same kinds of anti-patterns one sees in general application design. I try to take a close look at these in the book, with one chapter focusing largely on concurrency and object oriented design, which are essential to DI but that are often not associated as such.
InfoQ: Introducing your book Bob Lee, creator of Guice, says that DI support will eventually become just another language feature, "a construct for importing instances". What do you think about that?
Dhanji: I agree with Bob's metaphor. It is already unthinkable to start out writing a large application these days without some kind of DI library support. Almost all modern enterprise frameworks have a core DI component to them. I understand even EJB has something like this now.
There is a more fundamental issue at hand, which is that DI is itself a workaround to a deficiency in the language. While it does give us great savings by reducing repetitive code and making code more tolerable to change, ultimately a complete language should not require this of us. Bob's point is that we will eventually incorporate DI not as a third party framework, but as a core part of the platform itself. In much the same way as you use Collections today.
InfoQ: On your book you list several best practices and patterns for using DI. What are some of the worst ways you've seen people misusing DI and DI frameworks (anti-patterns)?
Dhanji: Oh, I have seen plenty of these! All of the anti-patterns I warn about in my book are from real life experiences. I guess the main problem is when people see DI as a hammer, everything becomes a proverbial nail. The easy support for aspect-oriented programming (intercepting method calls and modifying behavior) is probably the most abused of DI framework features. People get really excited when they see the things that are possible, and quite often lose sight of what is maintainable, and the original problem they were trying to solve, and that DI is intended to solve.
Despite the hype, you do not need to replace the "new" operator with injection everywhere you see it.
InfoQ: In what direction would you like to see DI frameworks moving to? What do you think should be expected in the future?
Dhanji: I would like to see more modular extensions and a greater focus on early error detection. There are some static analysis tools we use to describe and analyze application structure (like Guice's grapher, for example). We took care to build in support for this in Guice natively, I feel a lot more can be done in this area in further reducing boilerplate code and the potential for errors.
As for extensions, we are planning to support unified application lifecycle and extend the error-checking and type-rigor better for web applications. I would like to see all DI frameworks evolve in this area a bit further, rather than rushing to support the fancy library or idiom of the day.
InfoQ: On your book you mention that as DI frameworks have been evolving, they have been taking better advantage of Domain Specific Languages. Would you like to elaborate a little on this?
Dhanji: DSLs are a bit of a fad these days, particularly in API design where they have seen a lot of adoption. However, the trendy nature aside, they are remarkably concise and useful in capturing declarative intent. A lot of what DI frameworks do (binding implementation details, AOP interception, scoping) is describable as collections of declarative statements or goals. In this sense, DSLs are extremely useful in configuring a DI framework. Guice uses an embedded DSL (sometimes called an internal DSL) to capture configuration, which is basically a Java builder object emulating a special language. With Guice 2.0 we even support a DSL to intuitively map servlets and filters to URL paths in web applications.
InfoQ: Would you like to tell us a little bit about how DI is used in Google? As I've read on your book, Guice is used in several high profile products like Google Wave.
Dhanji: At Google we take testing very seriously. As a result DI is a central concept in nearly every engineer's toolbox. These days every Java application at Google is also a Guice application. We have found its features (such as type-safety, early error detection and focus on modularity) invaluable in building large, maintainable applications. We have numerous success stories from all around the company, in reducing boilerplate and making it easier for new engineers to come on board and learn the complex inner workings of legacy code.
With Google Wave, we use Guice in nearly every part of the application, including the new ServletModule which completely eliminates the need for xml-based configuration of servlets and filters. Our learning from this process has been that idiomatic, modular Java is far easier to rationalize and design with. For example, we were able to compartmentalize, combine and pull in various services dealing with authentication and site security as simple Guice servlet modules.
This has made Wave flexible and adaptable to ever changing security and user load requirements.
InfoQ: Recently there has been much debate regarding the conflict between JSR-330 ("Dependency Injection for Java") and JSR-299 ("Contexts and Dependency Injection for the Java EE platform"). What is your position on this matter?
Dhanji: Long ago (when the world was still young), I was involved in an effort to standardize DI along with Larry Cable, Rod Johnson, Bob Lee and others. That effort did not get far as we wanted, so I am glad to see things are happening again now.
As I understand it, JSR-330 deals with basic dependency injection for Java SE and JSR-299 adds a whole bunch of extra services for Java EE containers. There was some confusion initially due to a change in focus of one JSR and a late game submission of the other. I believe the spec leads of both JSRs are now working together to reach a mutually satisfactory conclusion where 299 will build on top of 330.
Personally, I do not use EE anymore and I am not involved in either spec, so I do not have much insight into the details surrounding them.
InfoQ: There are several books on DI framework specifics, but yours takes a different approach by presenting the fundamental concepts behind DI, before looking every time into framework support. What do you think would be the most valuable take away from your book for people that have just found about DI and what for seasoned users of DI frameworks that want to take it to the next?
Dhanji: I would like people to consider design a bit more. If my book has opened up how care taken makes for good reusable and concise design, then that would make me very happy. DI as a concept is just one window into the art of creating applications--and let me stress that point very clearly, it is an art, not a science. Hitting the sweet spot between modularity, performance and readability is quite hard and is only something that comes with a lot of practice and experience. I've made a whole host of mistakes in the process of writing this book and my career in general, these mistakes have been invaluable in teaching me how to and how not to approach design problems.
UPDATE: The first five (5) people that comment on this article, win a PDF version of the book from Manning Publications Co.
More fun to read about patterns
DI becoming more important but it's still not that popular
Re: DI becoming more important but it's still not that popular
anyone already got a message?
DI support will eventually become just another language feature, "a construct for importing instances"
This is exactly what Noop will have (new language proposed by Google engineers).
Ronny Kohavi Dec 12, 2013
Christian Legnitto Dec 12, 2013