Dependency Injection Tools still have some good years left…

 

…as long as we’re writing code in a static typed language anyway.  Dependency Injection the pattern isn’t going away, but it’s full time to reconsider Dependency Injection / Inversion of Control tools.

A couple weeks ago there was quite a bit of backlash against the usage of Dependency Injection (DI) and Inversion of Control (IoC) tools.  The pantheon of No Fluff, Just Stuff programming heroes made a game out of mocking Dependency Injection here and here.  My CodeBetter mate, Scott Bellware, even had some negative things to say on Dependency Injection tools (which I think is partially caused by him cutting his teeth on Spring.Net  ;) ).  I didn’t respond because I was deep into StoryTeller and didn’t quite know what my response would be anyway.  I’ll admit that the practice of pulling interfaces out and opening up constructors just to slip in mock objects is beginning to feel clunky in this era of TypeMock and duck-typed languages.  One of the things I concentrated on with StructureMap 2.0 was making the configuration easier to use by programmatic alternatives, less Xml overhead, and making StructureMap less intrusive, but StructureMap is still there in your code.  I don’t find it hard to use or distracting in the slightest, but maybe I need to start seeing it that way.

Give me Ruby or Python and I probably won’t feel as much need for a StructureMap.  That being said, I still think there are plenty of good reasons to use dependency injection besides the stereotypical unit testing scenarios (you’ve never needed an IoC tool just to attach test doubles anyway).  I’ve used my own StructureMap DI tool continuously for almost 4 years now and I’ve probably pushed the technique about as far as anybody (except for Aspect Oriented Programming (AOP) where I happily lag the curve).  Here’s a list of usages for DI as a pattern with and without an IoC tool that I’ve found beneficial:

  1. Flexible deployment options.  For example, last year I worked on a system that ran components on 3 different servers with a couple different remoting connections.  When we first got the system you couldn’t run the full stack without deploying the code to a windows service and an ASP.Net application.  Feedback was slow.  We hid the service points behind abstracted interfaces and started pulling the dependencies with StructureMap.  Once we made it to that point we simply made a different StructureMap profile that ran both the web client and server code in a single AppDomain.  The feedback cycle got quicker.  Debugging was easier.  We were able to write functional tests against the business rules engine because we could easily activate the code in process at will.  In case you’re wondering, we did have some automated tests fully end-to-end as well to make sure that the real communication and deployment configuration worked. 
  2. Stubbing out inconvenient services during development.  My last project was a .Net client in front of a balky Java web service.  The web service development often lagged the .Net code and was frankly a pain in the neck to install even when it was ready.  We used a “Stubbed” Profile in our StructureMap configuration to switch between a fully connected mode and a mode that talked to an in memory repository.  While you can make the switch by command line arguments, we redirected the application with a pair of batch files called “ConnectMe” and “StubMe” just to switch the default profile in StructureMap.  No hard wired stubbing or conditional compilation necessary.
  3. I think using DI leads to more self-documenting code.  I like being able to understand the dependencies of a class just by looking at the arguments to its constructor function.  I think it makes the code be more transparent by pointing to the class’s dependencies and configuration.  As pointed out originally by Jacob Profitt, this can be construed as a massive violation of encapsulation that can make a class harder to use.  That doesn’t concern me particularly because I use StructureMap to chain all the dependencies together in this case so that the client of an interface doesn’t need to know anything about the constructor functions of its dependencies.  Very few concrete classes should end up being directly exposed to the IoC tool.  Oddly enough, I’m generally not too concerned about the binding to StructureMap since I can pop into the code at any time to add features or fix problems.
  4. “Push” configuration is better in many ways than “Pull” configuration.  I use an IoC tool for all custom configuration needs.  Configured properties are just “pushed” into the classes that need them by the IoC tool.  The configuration now “knows” about the code but not the other way around.  My service classes are now completely usable in whole new settings because they aren’t coupled to a configuration file.  More on configuration management with an IoC tool at the StructureMap homepage.
  5. Reuse.  I’ve found that focusing on composing a system into cohesive classes with loose coupling to each class’s dependencies will allow for much simpler reuse.  If you can replace the dependencies for a class at will you can take that class and use it in an entirely new context when the need arises.  I’ve been able to take big chunks of a rules engine that ran in a transaction processing pipeline and use that same rules engine inside a web service.  We didn’t have to change a thing in the rules engine, just push in different implementations of it’s dependencies.  Having the engine decoupled from its configuration also made it more reusable when we needed to pull the configuration from an alternative source in the new web service.
  6. Easy to change the behavior of the system by swapping out implementation of some of the services or adding new components to the system.  One of the common things to do with an IoC tool is to define Chain of Responsibility handlers in the IoC tool so that it’s easy to plug in new handlers or reorder the existing handlers to add or change behavior.
  7. Built in Environment Tests.  I don’t know if any of the other IoC tools besides StructureMap has them, but I’ve used them to great effect in the past.  It’s especially valuable for distributed systems development and for highly iterative development that requires very frequent testing deployments.
  8. If you want pluggability for your own services, the Provider model sucks compared to any of the IoC tools.  Seriously, the implementation of the Provider model is limited in capability compared to any IoC tool.  If you want pluggability, I think you’ll find that any of the common IoC tools are more useful than building your own Provider type.  Specifically, with an IoC tool you don’t need to inherit from a particular base class, you have more freedom to compose dependencies rather than build one gigantic, overweight class, and you have more options for configuration storage and runtime pluggability than the Provider model supports.

 

Regardless…

So, is Dependency Injection still good, or just baggage from yesterday that needs to be cleared away so we can continue to progress?  It seems perverse to me to be wrestling with this question since Dependency Injection is still relatively new and hasn’t even come close to crossing the chasm inside the .Net community.  Heck, Microsoft is just starting to support DI strategies in some of the Patterns and Practices work and Acropolis (but clumsily)!  It’s a harder question for me since I’ve invested quite a bit of time over the last 4 years building and using a DI/IoC tool.

I think it’s fair and accurate to say that some of the goals of using Dependency Injection in a static typed language can be realized through simpler mechanisms in dynamic typed languages.  I still think you want to use Dependency Injection in Ruby because the rules of OOP still apply, but maybe the fancy IoC tools largely go away.  I could use much more experimentation, but Ruby style metaprogramming does seem much simpler in mechanics and readability to me than using DI engines and AOP in C# to enrich behavior.  Despite how many words I just used above to extol the benefits of IoC/DI that I’ve already enjoyed, it is time to reconsider this technique’s place in my toolbox as we move forward.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Bob,

    I don’t know about the Java tools, but you can use any of the mainstream .Net IoC containers without any Xml or Attribute mess now. Don’t project your Spring-driven Xml hell into my world please.

  • bob

    The Emperor has NO CLOTHES!

    There are so many incredible things you can do with a computer, and connecting together your Java Objects with XML is way way down on the bottom of the list.

  • http://Bryan.ReynoldsLive.com Bryan Reynolds

    @Colin and @Brad,

    Colin recommends a great book. I am a noob to many of these patterns and practices and have been studying them daily. Robert C. Martin’s book is excellent.

    Bryan

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @David,

    This might be just me, but I wouldn’t try to use any kind of decorator chain or AOP interception to mark transaction boundaries. It’s too much magic happening outside and away from the code that’s doing the actual transactional work.

    My choice is to do transactions explicitly or through a Unit of Work in the ORM of your choice.

  • David Martines

    I see how you can add logging, notification , etc. using a decorator chain via DI/IoC. You also mentioned transactions – How would you use a decorator chain to handle transactions?

  • http://colinjack.blogspot.com/ Colin Jack

    Good post.

    Personally I’m finding the debate on this and a few other issues is getting a little over the top. It seems like as soon as something starts getting a few headlines you get people jumping in to say use it everywhere then after a while everyone rushes off to some other place and they start saying the old approach is rubbish. Its like the cool kid at school who would slag off the school dance just to make everyone else feel unworthy.

    Anyway I’m in favor of the use of dependency injection where you actually think there is going to be a need to replace the dependency.

    However having heard some awful suggestions for design changes to allow IoC in, and having tried some myself, I do think you need to think carefully about WHERE in your application to use it. Slapping interfaces on every class, using IoC factories to create all your (maybe business/domain) classes and making sure you can inject every dependency (even dependencies within a layer that should be encapsulated) is not necessarily going to produce a wonderful design.

    @Brad Mead – I would suggest the book by Micah Martin:

    http://www.amazon.co.uk/Principles-Patterns-Practices-Robert-Martin/dp/0131857258/ref=sr_1_1/203-1018479-7827132?ie=UTF8&s=books&qid=1189668368&sr=8-1

    Half the trick is knowing when to use and not use techniques explored in this and other books though.

    @Nate – I’m with Jacob, I like DI but I don’t like the attitude of some of the people who push DI (not speaking about this blog!). I think this is the same problem ORM had for a while, some of the people who were very well known in the ORM space were so rude/arrogant that it was a big turn off, luckily its all moved on a bit now.

  • http://scruffylookingcatherder.com Jacob

    @Nate: I’m happy to give you any love you stand in need of. Say the word and I’m there for you…

    Also, I’m not railing against DI. I give it plenty of chance. It has its uses, which you’ll see I admit in some detail if you read through my DI blog posts. Unfortunately, many of the DI true believers *do* act arrogant when advocating DI uses and become dismissive when you so much as express doubt, offer alternatives, or ask penetrating questions. To many, any exploration of DI’s costs or any indication that you don’t embrace DI for all situations and all projects is enough to label one as closed-minded or accuse one of not giving DI a chance.

    Finally, there’s a difference between “can be effectively applied” and “is worth applying”. You can use it in every project if you want to, but I don’t see the benefit for self-contained, stable projects that make up the bulk of non-enterprise development. Implementing DI has costs associated with it, and those costs are non-zero. Blindly accepting those costs for all projects when there’s no clear need sends up YAGNI flags to me.

  • http://kohari.org/ Nate Kohari

    @Jacob:

    Where’s the love? :) I still don’t quite get why you continue to rail against the “arrogance” of DI practitioners. DI isn’t some sort of cult. It’s just a tool, and it’s one of many that I use on a daily basis. I don’t think anyone is really saying that DI is the only way you can get clean code… but on the other hand, I don’t understand why you’re so firmly against giving it a chance. To me, that’s equally as closed-minded as someone that says DI is the “one true way”.

    I also tend to believe DI can be effectively applied to all projects. You might use a different framework, but unless your application amounts to 100 lines or code or less, DI is a useful tool.

  • http://scruffylookingcatherder.com Jacob

    @Oran: People like you who equate ignorance of DI with being “uninterested in improving the way [you] code” are the single greatest detriment to DI, I think. The hidden assumption is that only idiots don’t use DI. Such statements come across as incredibly arrogant. DI is useful, sure, but it isn’t universally so. There are whole strata of developers who don’t need it and shouldn’t be forced to defend their coding practices just because DI is useful in other project types. The casual disdain you show is the source of the DI backlash that careful practitioners like Bob Lee and Jeremy Miller go to great lengths to mitigate.

  • http://orand.blogspot.com Oran

    It seems like the root motivation for most pro-TypeMock arguments is “it enables me to not change how I code and think,” with the unquestioned assumption that “the way I code is best, or at least better than the way these DI fanatics code.” There also seems to be a secondary argument of “TypeMock also doesn’t pressure me to take the time to understand the additional non-test-related benefits of DI.”

    Why would you trust your developers to not use TypeMock poorly if they are uninterested in improving the way they code?

  • http://scruffylookingcatherder.com/ Jacob

    @Jeremy and @Chuggle

    Yeah, I’ve had that discussion out. I’m not saying that DI doesn’t have benefits. I’m just saying that TypeMock takes care of those benefits that relate to mocking for unit testing without requiring that you change how you code. I even made a handy (to me anyway) little chart designed to show the cleft points between Factory, DI, and TypeMock (Dependency Injection with both a framework and by hand).

    I must admit in addition, thought, that I could care less what type of murder TypeMock lets you get away with. All tools let you get away with any number of types of murder. The more powerful the tool, the more destructive poor choices can be. Indeed, I find objections to a tool because “it is too powerful” to be a bit strange. I could care less what damage it could do if used poorly because I trust myself and any developers I hire or approve to be hired not to use it poorly…

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Nate, It’s all good. Don’t count on it bringing you fame and glory though;)

  • http://kohari.org/ Nate Kohari

    @Brad Mead: The bad news is that the workflow of ASP.NET is so rigid that it restricts your ability to use DI, at least when you’re talking about injecting Pages themselves. Some frameworks have support for this, though…

    For a quick intro to DI in general, check out:

    http://www.codeproject.com/cs/design/introducingcastle.asp
    http://www.castleproject.org/container/gettingstarted/index.html

    And, in keeping with my apparent theme of spamming Jeremy’s blog with references to Ninject: http://ninject.org/users-guide.html

    ;)

  • Chuggle

    @Jacob – I personally dont like TypeMock as it lets you get away with blue murder, I try and use it sparingly and if possible design around any problems that cant be solved with RhinoMocks (not always successfully I have to admit, but I treat TypeMock as a last resort)

    But to answer your question – yes absolutely as long it provided more benefit than the DI approach, the main one in my mind is the natural decoupling you end up with, which could be bypassed when using TypeMock

    Also I think Dependency Injection sounds cool (which is the real reason I use it)

  • Brad Mead

    I read these posts with great interest. Up front i’ll say with regard to IoC and advanced OOP pattern techniques I am a hopless noob. What I would like to understand (as a C# web developer) is where I should start…? I need to bite off small chunks and implement these techinques whereby I can rely on my proficiency with them to do actual work from day to day.

    Where’s thes best place to start (other than re-reading the Strategy Pattern in “Head First Design Patterns”)?

    Thanks, Nooby.

  • http://kohari.org/ Nate Kohari

    @Joe Ocampo: I wrote it, does that count? *grin*

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Jacob,

    There’s also the question of whether or not TypeMock does all of those things better than an IoC tool does. It might help strictly for unit testing, but I don’t see how it does much for everything else. Can you really say that using a tool that uses the profiling API is really simpler to use and understand than simple constructors and setters?

  • http://scruffylookingcatherder.com Jacob

    Chuggle: What if you can “smarten up your design, allow for proper code coverage and develop away without the need for a live database or any other external dependencies” without DI? Would you still use it? That’s the question I ask because with products like TypeMock available, you can have those advantages without having to change how you code.

    Which shouldn’t detract from what Jeremy is saying here. He makes some excellent points about why you’d want to use DI without once referring to the things you mention. Frankly, I wish more people would be as direct and thorough as this post from Jeremy.

  • http://www.lostechies.com/blogs/joe_ocampo Joe Ocampo

    I was wondering has anyone tried Ninject?

    http://ninject.org/

  • Dan

    Ah yeah, I see now. My mind was not prepared for understanding that IoC tools do service location :))

    Nice explanation, thanks so much

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Dan,

    “Service Locator” just means this:

    IService service = ObjectFactory.GetInstance();

    in the middle of some method. It’s grabbing an instance of IService from the IoC “Container”

    As opposed to Dependency Injection like this:

    private readonly IService _service;
    public SomeClass(IService service)
    {
    _service = service;
    }

    Effectively all IoC tools do both Dependency Injection and Service Location. Any place in this post that I said Dependency Injection you can largely stick in Service Location as well.

  • Dan

    I have curiosity too for the question Ollie asked, as I have never tried a dynamic typed language.

    I imagine something like C# but without compiler checking types, but is a bit strange after many years hearing about the benefits of type safety.

    And about the service locator David Hayden is talking about, is passing the dependencies through a container object ?
    Excuse my ignorance

  • Ollie

    Can someone explain exactly with no fluff or misdirection why a dynamic language doesn’t require such complicated overheads to support DI.

    I also find it bizarre that the programming world is becoming like the rest of society and trying to find ‘the next big thing’ without fully realising what we currently have, I don’t think the use of DI has matured as far as possible yet – where it could take us I don’t know. But what I do know is there are so many developers out there who haven’t got a clue about such things.

  • http://davidhayden.com/blog/dave/ David Hayden

    Just thinking out loud on the above comments and this topic…

    I can still use a service locator from within a class to get its dependencies and get all the wonderful benefits of using stubs, polymorphism, etc. Dependency Injection isn’t the only way to help isolate (abstract ) the dependencies on other classes and subsystems.

    I, personally, think Dependency Injection comes with a bias towards unit testing, etc., and I don’t mean that negatively.

  • http://kohari.org/ Nate Kohari

    Very well put. I agree that in more malleable languages like Ruby, DI has less of a purpose, since a lot of the magic that DI provides you is built into (or overridden by) features of the language itself. However, for those of us in the static language world, DI offers a great deal of flexibility.With DI, writing an application in C# is like building a wall of bricks, whereas without it, it’s like carving a wall out of one big chunk of marble. I’m also fond of saying that developing in a dynamic language is kind of like sculpting soup. :)

    I’d love to see a language that has inversion of control built in… it might not be useful in practice but it would be an interesting experiment.

    I also use DI to program against “stub” services during development — in fact, that was one of the primary reasons I wrote Ninject. For example, the project I’m currently working on authenticates users against an Active Directory, which I don’t have access to on my development machine. All I need to do is create a stub security service that pretends to do the authentication, and I can develop the rest of the app disconnected from the real environment. I don’t need to set up a test environment or deploy it to the production server until I’m ready.

  • Chuggle

    I honestly dont understand why people dont like DI – it smartens up your design, allows for proper code coverage and it means I can develop away without the need for a live database or any other external dependencies (obviously helped by using RhinoMocks)

    Its like the people who say TDD is no good….if it dont work you aint done it properly

  • http://iancooper.spaces.live.com Ian Cooper

    The key is that the push towards dependency injection from TDD encourages the use of the strategy pattern which enables polymorphism as the solution to the ‘Be open for extension, closed to modification principle’. The difficulty with invoking the strategy patten is knowing where to place your bets; TDD exercises your code so that you make better bets about where you will need to use the strategy pattern (which is what DI or IoC are). Dynamically typed languages don’t have to make this bet, as polymorphism is always possible – you don’t have to declare it, you just do it. Still you need to be able to replace the thing you depend on, so you may still want to provide the concrete instances by constructor/setter where they might change, but the ability to add that additional constructor or setter is unlikely to break the bank if you do it when you need to. So with a dynamic language unless you know you need different versions, you can do the simplest thing.

    Interestingly its more of an issue with C# than Java, as Java implicitly supports virtual methods, so you can more easily subtype concrete arguments, but they are explicit in C#, so you need to pre-decide your interface..

    http://iancooper.spaces.live.com/blog/cns!844BD2811F9ABE9C!476.entry

  • http://joeydotnet.com/blog joeyDotNet

    #2:
    Especially when you’re driving the design top-down and aren’t worried about implementing a database immediately. It’s very easy to still flesh out your repository interfaces and create stub (in-memory) implementations of them. This allows you to have a (mostly) fully functional system, without the need for a database. I’m doing this in our current project and it’s been a great success so far. In our case, we’re having to use Commerce Server as our “database”, so it’s been great to stay out of the CS 2007 muck while we’re fleshing out the UI, Services and Domain Model.

    #6:
    Another great thing that an IoC can facilitate are decorator chains as you noted above. The ability to change the behavior of the system by moving around “links” in a “chain” can be quite powerful and can be done rapidly.