Deciding When to Use DI

by Jacob 18. September 2007 12:58

Scale Apple & Candy I’ve been musing about software architecture lately and trying to come up with a framework to help choose when to go with more as opposed to less—something that’ll help me feel less arbitrary in my choices. I mean, software design is something of a dark art, but how much of that is inherent and how much is simply being too lazy to formulate good internal guidelines?

My latest ruminations have revolved specifically around Inversion of Control in general and Dependency Injection in specific. Here’s the thing: for the development I do right now at a small reading glasses company, I’m reluctant to implement any of the stronger separation of concerns architectural tools like IoC and a DI framework. The DI zealots would draw from that the conclusion that I am a sub-standard designer and a compromised developer—at least, judging from explicit claims that every project should start out with formal DI (please note both the "every" and the "should").

Pain is an Efficient Teacher

Perhaps too efficient. Most developers have had the experience of working on a project where decisions made in the expedience of the moment came back to hurt them. In a recent DotNetRocks episode, Scott Cate gives an example of hard-coding to a specific search engine and coming to find that they need to generalize in order to allow alternatives. He wishes that they had used a DI framework from the start (in this case, Castle Windsor) to make that an easy change. Scott tells about how they were lucky this need was discovered in time for a major release upgrade so they could take the time to go the full DI route.

There’s two problems with this example when translating to my own situation. First, Scott’s is a commercial product that they sell to large clients and thus the scope is far beyond anything I work on here. Second, I wonder how much pain was really involved in making the change.

You see, pain magnifies itself in memory. You consider all the might-have-beens and how much the problem could penetrate even as you work to ameliorate it. And you consider things you can do in the future to avoid this pain—both the immediate pain and the imagined pain of all those might-have-beens.

The YAGNI Nazi

This tendency to artificially inflate potential scope is the driving force behind YAGNI. YAGNI is the reminder that you can go too far in countering the mere possibility of future pain and that you can plan too far in advance of actual need. I’m a huge fan of YAGNI simply because it has allowed me to realize significant time savings and produce useful software for clients quickly and efficiently.

In many software design discussions, however, I feel like a lone YAGNI voice in an over-designed wilderness. I’m accused of negligence or stupidity (though typically through implication as opposed to outright accusation) because I look for the justification of larger design patterns before blindly implementing them. People make the unearned assumption that understanding a given principle must mean that I would adopt it. This comes through loud and clear in the discussions with DI proponents. It seems entirely foreign to them that I could both understand it and decide to give it a skip on some of my projects.

Sometimes this judgement comes in the form of a logic chain. This happens when designers use the strengths of one principle to piggy-back in a second. Unit testing is most often the piggy-back victim here. That’s because the benefits of unit testing are well-understood and apparent in projects of even minimal scope. Scott Cate admits in that DotNetRocks episode, for example, that a large part of his current push for the Model View Presenter pattern as well as DI is to facilitate unit testing (when he also took pains to point out that implementing Castle Windsor is not without cost he went on my list of DI heroes).

The problem with a logic chain, however, is that you’re right back where you started if a link breaks. What if I can achieve strong unit testing without IoC and DI?

So here is my YAGNI wisdom (for what it is worth): you don’t protect yourself from future change by throwing every possible technique or pattern at every project. You protect yourself from future change by refactoring ruthlessly to keep your code as change-ready as possible.

The Bottom Line on Dependency Injection

So here’s where I think I’ll come down as a rule on implementing DI: I’ll use it as soon as I actually need to support multiple services in a given object. Since I don’t need DI in order to mock dependencies in unit testing (yay TypeMock), this means that I’ll look to implement DI when I have to support multiple services in a given object in production. I have two examples of related projects here that will serve as useful test cases.

The first is a need to integrate customer orders into Dynamics GP. We have many customers who send us orders in a variety of ways and with a variety of processes for approving and tweaking them before we let them hit our system. It’d be nice to have a single module integrated into Dynamics GP that can accept orders in the variety of formats we end up with and go to town. I’ve already got this project up and running for a single customer using a generalized interface and I think DI can help extend that further faster than I can without it.

The second is the initial processing when we receive EDI documents from our clients. Since EDI X12 isn’t really a standard so much as a soup of possible ways to do things, each customer tends to put their own unique spin on what fields are significant and how they should be interpreted. I’ve hated our current EDI software for months (and not just because it uses FoxPro at its base) and I’d dearly love to pull that processing into an internal framework I can use and extend on my own.

Both projects will take me a while, which is appropriate because I’ve been saying all along that DI seems like something suited to larger-scoped projects. I’ll post my experiences as I go, assuming I actually get the time to tackle either one.

Both of these examples are also an inversion of typical DI examples because in both I technically have a service that needs to act on multiple objects. That said, I’ve been an architect long enough to understand that while services and objects might differ conceptually (though defining either is an exercise in nit-pickery), it’s trivially easy to turn each into the other (if you bother differentiating them at all—see nit-pickery above). Sometimes it is quite useful to invert them as I plan to do here.

Tags: , , , , , ,

Programming

Comments


September 21. 2007 05:25
Peter Bell
YAGNI is always a good principle, but in my experience, DI is a quick and easy win once you get it  - for any size of project. I develop a fair bit in ColdFusion and wrote my own little DI engine (400 lines of code) which I use as part of an in-house framework for all of my apps. I then layer on top of it a bunch of convention over configuration features that fit well for my use case, but I really don't find DI takes any more time or effort than a non-DI approach and I find it simplifies the architecture of my apps.

For me the comparison would be to using (say) Visual Studio over notepad. I could argue that the additional complexities of VS (or Eclipse or whatever) aren't really required to edit text files. I'd be right, but I still think in the long run I'd be better off and more productive getting up to speed with a modern IDE as the complexity can pay for itself in terms of productivity once you're comfortable with it.

That said, there are plenty of Ruby and Smalltalk developers who do just fine without DI at all, so it's also a function of the way you architect your apps as to whether it is worthwhile . . .


 Andy Yates 
September 21. 2007 09:03
Andy Yates
Coming from the Java world of DI & IoC & I have to say that my life becomes easier when systems are designed in a way where concerns are separated. This pattern of developement is enforced by IoC & DI patterns working along side a design by contract ethic.

I do agree with you that DI is not the solution to everything. I prefer to program in a way that lets me use DI as & when it becomes necessary. Otherwise PicoContainer & Spring get left well alone (I think that subscribes to YAGNI well enough for my likings). For example in my current project our group has 6 services all of which have local & remoting versions. In the normal code base I do not use a DI engine & even let people create their own instances of the services & when they need them. However I have a web application which also uses these same services. Once in the web application I switch to using Spring & let it deal with the business end of service injection. The two practices work side by side but each has it's place. One where end users just want to construct a service & use it; another where I want the same service available everywhere.

@Peter
Yup there's plenty of Ruby & Smalltalk developers who get by without DI. I just think that these langauges are better at getting around the reasons why we have DI in Java & C#.  


September 21. 2007 14:11
Jacob
@Peter: Yeah, I've heard that line before. Repeatedly. Here's the thing: technical expertise is a dependency that is often overlooked when discussing these things. When you implement DI, you create a minimum skill limit for anyone following you to be able to maintain or even read your code competently. You tacitly admit as much when you say "once you get it". There's a barrier to understanding there. Don't pretend that DI is trainwreck proof. Everybody glides over that initial hump as if it is an individual commitment and it isn't--it's an institutional one.

Comparison to Visual Studio vs. notepad is misleading because it implies that DI should be a perfectly acceptable minimum skillset for every project. That's exactly what I mean when I talk about being considered a sub-standard developer just because I don't make DI a miminum required skillset for anyone following me. This accumulation of "small" barriers and costs is what I meant in my post just previous to this one when I talked about small companies being subject to death by a thousand cuts. YAGNI to me means holding those cuts down to the absolute minimum needed to get the current job done.

@Andy's comment is a good balance, IMO. To me, good architecture is all about balance...


September 24. 2007 23:32
Sergiu
I believe in YAGNI - it is a very sensible idea from business standpoint. However I don't consider DI as YAGNI, as there's not much to do - either way you need to write the linking code, either explicitly in the code, or as part of some XML config file (like in Spring). However not using DI, especially in a team that has more than 1 developer, tends to increase the risk of writing poor code, especially under time pressure. Standardizing on some DI and establishing some good design and coding practices should alleviate this problem.

Now regarding EDI and X12 - you're right, it's a soup, and it's not that easy as it initially appears. You need a serious product/library to deal with EDI files and their processing. We sell one (called XEngine) that should help you, we've put more than 7 years in it solving EDI problems our customer face daily.


 throwspoop 
September 27. 2007 17:52
throwspoop
I think what your getting at is that in some blog circles DI and LoC conversations are all the rage . Give it time and they will see a brighter coin in the distance, drop the one they are coveting and run over and pick up the newer, less familiar (note sexier) one (this will continue ad-infinitum).


May 25. 2009 01:32
4396508
think what your getting at is that in some blog circles DI and LoC conversations are all the rage . Give it time and they will see a brighter coin in the distance, drop the one they are coveting and run over and pick up the newer, less familiar (note sexier) one (this will continue ad-infinitum).  Thanks....


July 19. 2009 07:13
club penguin cheats
I develop a fair bit in ColdFusion and wrote my own little DI engine which I use as part of an in-house framework for all of my apps. I then layer on top of it a bunch of convention over configuration features that fit well for my use case, but I really don't find DI takes any more time or effort than a non-DI approach and I find it simplifies the architecture of my apps.


vallejo personal injury attorneys
Deep study of software architecture will let one design a framework that will allow him or her to choose when to go with more as opposed to less arbitrary choices. "Inversion of Control" and "Dependency Injection" are two key branches of knowledge that will assist you in doing exactly that. Architectural tools like IoC and a DI framework are the pillars of this complicated goal.

Information

    Calendar

    <<  May 2012  >>
    MoTuWeThFrSaSu
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    View posts in large calendar
    Disclaimer
    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2012 Scruffy-looking Cat Herder