- Black Sheep - http://blacksheep.parry.org -
DIY-DI
Posted by Chad Parry on March 15, 2010 in Software Development | 16 Comments
The “dependency injection” (DI) technique is a way to improve testability and maintainability of object-oriented code. Typically adoption of dependency injection is coupled with adoption of a dependency injection framework, such as Guice [1] or Spring [2]. These materials show how dependency injection can be accomplished without any framework. The same benefits provided by frameworks can be realized using “do-it-yourself” (DIY) handcrafted code. This model is named DIY-DI, pronounced die-die.
Update (May 29, 2010): I added a comparison with Guice and more polished code snippets to the DIY-DI manual.
Article printed from Black Sheep: http://blacksheep.parry.org
URL to article: http://blacksheep.parry.org/archives/diy-di
URLs in this post:
[1] Guice: http://code.google.com/p/google-guice/
[2] Spring: http://www.springsource.org/
[3] State of the Art Testability: http://docs.google.com/present/view?id=dg4jbg5c_7cwkvrhfq
[4] PowerPoint: http://blacksheep.parry.org/wp-content/uploads/2010/03/State-of-the-Art-Testability.ppt
[5] DIY-DI: http://blacksheep.parry.org/wp-content/uploads/2010/03/DIY-DI.pdf
[6] DIPresentation: http://blacksheep.parry.org/wp-content/uploads/2010/03/DIPresentation.zip
[7] : http://is.gd/csF7A
Click here to print.
Copyright © 2008 - 2010 Chad and Elisa Parry. All rights reserved.
16 Comments To "DIY-DI"
#1 Pingback By Do it Yourself – Dependency Injection On May 26, 2010 @ 9:10 am
[...] friend of mine has put together a set of documents which talk about do-it-yourself dependency-inject. Being that I am a fan of DI and how it helps with testability I wanted to share it with you. It is [...]
#2 Comment By Rusty Wright On May 26, 2010 @ 11:27 am
Page numbers would have been nice on the pdf, in case I drop them and they’re not stapled and get out of order.
#3 Comment By Rusty Wright On May 26, 2010 @ 11:29 am
Sorry; before I criticized I should have thanked you for such a nice write up!
Thanks again; this is very helpful.
#4 Comment By Chad Parry On May 26, 2010 @ 6:25 pm
Thanks Rusty. I’ve added page numbers.
#5 Comment By Marcel Doru Popescu On May 26, 2010 @ 10:36 pm
Yes, this is put together nicely, thank you.
#6 Comment By Bino Manjasseril On May 27, 2010 @ 7:24 am
Great write up and good examples! Thanks!
#7 Comment By Böszörményi Péter On May 27, 2010 @ 7:59 am
Hi!
I have a question about the article. In step 5 you removed the parameters from BookingService’s buy method, and added to the constructor. This modification introduced an – in my opinion – unnecessary state to BookingService. From this point, if i want to use this service, i always have to create a new instance (cannot share the instance across multiple invocation), and i always have to deal with the constructor’s parameters. Wouldn’t it be easier to use the BookingService’s earlier form (from step 4)?
ps: Sorry for my english, it’s not my native language.
#8 Comment By Chad Parry On May 27, 2010 @ 7:05 pm
Péter, the intention in step 5 was to make it easier to acquire a BookingService. I know that’s counter-intuitive, because of the reason you describe. The BookingService dependencies are not easy to construct. So callers would be over-burdened if they always had to say:
BookingService.buy(Account.getCustomerAccount(accountKey), new Trade(symbol, quantity), commission);
Most would prefer:
booking.buy();
Plus, those callers would prefer the looser coupling with accounts, account keys, trades, symbols, quantities and commissions.
Fortunately, in a DI-infected application, that extra BookingService state does not tend to create a problem. Anyone that needs a BookingService simply asks the injection framework for one, and a fresh instance is provided. If multiple instances were undesirable, then the BookingService could be left like in Step 4, and the request-specific state could be moved to a BookingClient class instead. Then BookingClient would have constructor parameters for accounts, trades, commissions and the BookingService instance.
#9 Comment By Nuttanart On May 27, 2010 @ 9:37 pm
I love this silde. I was finding for example like this a half year. DIY-DI, refactoring approach to make code testable and combing some OO principles. Better than many selling books. Thanks.
#10 Comment By Petter Måhlén On May 27, 2010 @ 11:06 pm
Hi,
Great ideas and very clearly expressed! I have a couple of questions, though:
- In your Injector examples, you always create new instances of the things that you inject. For a lot of object graphs you’ll probably want to reuse the same instance of some objects and inject that into multiple other objects. In such a case, would you typically cache that instance in the scope (making it mutable) or in the injector class or is that some third thing?
- I’m not quite with you on the “don’t use mock objects” issue. Could you elaborate on that? It feels like it is quite common that one object wants to trigger something to happen in a collaborator. Of course, the data exchanged between the objects can be represented as primitives/value objects, but the actual event of triggering something cannot as far as I can figure. I guess that could be made a part of the wiring up, but that seems like it would hide important and testable business logic. Using mock objects feels like the best way to check that sort of thing.
Cheers,
Petter
#11 Pingback By Tweets that mention Black Sheep » DIY-DI » Print — Topsy.com On May 27, 2010 @ 11:11 pm
[...] This post was mentioned on Twitter by skim, Jilles van Gurp. Jilles van Gurp said: Currently Browsing: [7] great article on do it yourself dependency injection and design considerations [...]
#12 Comment By Chad Parry On May 28, 2010 @ 5:22 am
Petter, my thoughts on caching mirrored yours. I didn’t get into it on the slides, but you can see the description of a clean technique in the DIY-DI.pdf. Look for the section titled “Caching” near the bottom of page 11.
Mocking is still necessary in some cases, like where the production objects need to perform operations in a certain order. So maybe the best advice is, “Think twice when you find yourself using mock objects.” I find that the more DI code I write, the more I use functional programming idioms. Pure functional programs still have complex interactions but they typically do it in a way that could be tested without mocks. For example, suppose you write a class that configures a static logger. You could have that class produce a token, as a proof that configuration was performed. Then any classes that need the log configured can ask for that token as a dependency, rather than calling the log configurator directly.
#13 Comment By Vlad Dumitrescu On May 28, 2010 @ 11:42 am
Very nice written and explained!
Do you happen to have any thoughts about using this with OSGi (or more precise with Eclipse plugins)? My first impulse is to use plugin scopes, but there is also the Eclipse platform with its tens of singletons and static stuff…
#14 Comment By Chad Parry On May 29, 2010 @ 7:08 am
Vlad, the concept of Eclipse plugin scopes probably doesn’t overlap with the concept of DI scopes. I think that’s just an example of how the term has been overused. The plugin scopes contain static state, so hardcoded references to them would make testing difficult. You could use DI for developing a plugin though. Write your own scope and injector classes like in the DIY-DI manual. Then you can also write helper methods in the injector class to provide each of the static resources in the Eclipse plugin environment.
#15 Comment By Vlad Dumitrescu On May 29, 2010 @ 10:14 am
Thanks for the suggestions. An Eclipse application usually involves several plugins and this is where it feels tricky. I think that what I meant with ‘plugin scope’ is what you mean by “your own scope”. The conclusion, I suppose, is that it’s not trivial.
#16 Comment By JB On September 3, 2010 @ 8:06 am
In your PDF manual you say to make trivial doGet and doPost methods for a servlet implementation. I can see how those methods would construct a RequestScope object using the passed in HttpServletRequest and HttpServletResponse objects. I can see how to get a SessionScope from HttpServletRequest.getSession but how do I get my ApplicationScope object?