I've been using Dependency Injection (DI) for a while, injecting either in a constructor, property, or method. I've never felt a need to use an Inversion of Control (IoC) container. However, the more I read, the more pressure I feel from the community to use an IoC container.
I played with .NET containers like StructureMap, NInject, Unity, and Funq. I still fail to see how an IoC container is going to benefit / improve my code.
I'm also afraid to start using a container at work because many of my co-workers will see code which they don't understand. Many of them may be reluctant to learn new technology.
Please, convince me that I need to use an IoC container. I'm going to use these arguments when I talk to my fellow developers at work.
I realize this is a rather old post, but it seems to still be reasonably active, and I thought I'd contribute a couple of points that have not yet been mentioned in other answers.
I will say that I agree with the benefits of dependency injection, but I do prefer to construct and manage the objects myself, using a pattern not unlike that outlined by Maxm007 in his answer. I have found two main problems with using 3rd party containers:
1) Having a 3rd party library manage the lifetime of your objects "automagically" can lend itself to unexpected results. We have found that especially in large projects, you can have vastly more copies of an object than you expect, and more than you would if you were manually managing the lifecycles. I'm sure this varies depending on the framework used, but the problem exists nonetheless. This can also be problematic if your object holds resources, data connections, etc., since the object can sometimes live longer than you expect. So inevitably, IoC containers tend to increase the resource utilization and memory footprint of an application.
2) IoC containers, in my opinion, are a form of "black box programming". I have found that in particular, our less experienced developers tend to abuse them. It allows the programmer to not have to think about how objects should relate to each other or how to decouple them, because it provides them with a mechanism in which they can simply grab any object they want out of thin air. Eg, there may be a good design reason that ObjectA should never know about ObjectB directly, but rather than creating a factory or bridge or service locator, an inexperienced programmer will simply say "no problem, I'll just grab ObjectB from the IoC container". This can actually lead to increased object coupling, which is what IoC is supposed to help prevent.
Wow, can't believe that Joel would favor this:
over this:
Many folks don't realize that your dependencies chain can become nested, and it quickly becomes unwieldy to wire them up manually. Even with factories, the duplication of your code is just not worth it.
IoC containers can be complex, yes. But for this simple case I've shown it's incredibly easy.
Okay, let's justify this even more. Let's say you have some entities or model objects that you want to bind to a smart UI. This smart UI (we'll call it Shindows Morms) wants you to implement INotifyPropertyChanged so that it can do change tracking & update the UI accordingly.
"OK, that doesn't sound so hard" so you start writing.
You start with this:
..and end up with this:
That's disgusting plumbing code, and I maintain that if you're writing code like that by hand you're stealing from your client. There are better, smarter way of working.
Ever hear that term, work smarter, not harder?
Well imagine some smart guy on your team came up and said: "Here's an easier way"
If you make your properties virtual (calm down, it's not that big of a deal) then we can weave in that property behavior automatically. (This is called AOP, but don't worry about the name, focus on what it's going to do for you)
Depending on which IoC tool you're using, you could do something that looks like this:
Poof! All of that manual INotifyPropertyChanged BS is now automatically generated for you, on every virtual property setter of the object in question.
Is this magic? YES! If you can trust the fact that this code does its job, then you can safely skip all of that property wrapping mumbo-jumbo. You've got business problems to solve.
Some other interesting uses of an IoC tool to do AOP:
Presumably no one is forcing you to use a DI container framework. You're already using DI to decouple your classes and improve testability, so you're getting many of the benefits. In short, you're favoring simplicity, which is generally a good thing.
If your system reaches a level of complexity where manual DI becomes a chore (that is, increases maintenance), weigh that against the team learning curve of a DI container framework.
If you need more control over dependency lifetime management (that is, if you feel the need to implement the Singleton pattern), look at DI containers.
If you use a DI container, use only the features you need. Skip the XML configuration file and configure it in code if that is sufficient. Stick to constructor injection. The basics of Unity or StructureMap can be condensed down to a couple of pages.
There's a great blog post by Mark Seemann on this: When to use a DI Container
IoC frameworks are excellent if you want to...
...throw away type safety. Many (all?) IoC frameworks forces you to execute the code if you want to be certain everything is hooked up correctly. "Hey! Hope I got everything set up so my initializations of these 100 classes won't fail in production, throwing null-pointer exceptions!"
...litter your code with globals (IoC frameworks are all about changing global states).
...write crappy code with unclear dependencies that's hard to refactor since you'll never know what depends on what.
The problem with IoC is that the people who uses them used to write code like this
which is obviously flawed since the dependency between Foo and Bar is hard-wired. Then they realized it would be better to write code like
which is also flawed, but less obviously so. In Haskell the type of
Foo()
would beIO Foo
but you really don't want theIO
-part and is should be a warning sign that something is wrong with your design if you got it.To get rid of it (the IO-part), get all advantages of IoC-frameworks and none of it's drawbacks you could instead use an abstract factory.
The correct solution would be something like
or maybe
and inject (but I wouldn't call it inject) Bar.
Also: see this video with Erik Meijer (inventor of LINQ) where he says that DI is for people who don't know math (and I couldn't agree more): http://www.youtube.com/watch?v=8Mttjyf-8P4
Unlike Mr. Spolsky I don't believe that people who use IoC-frameworks are very smart - I simply believe they don't know math.
As you continue to decouple your classes and invert your dependencies, the classes continue to stay small and the "dependency graph" continues to grow in size. (This isn't bad.) Using basic features of an IoC container makes wiring up all these objects trivial, but doing it manually can get very burdensome. For example, what if I want to create a new instance of "Foo" but it needs a "Bar". And a "Bar" needs an "A", "B", and "C". And each of those need 3 other things, etc etc. (yes, I can't come up with good fake names :) ).
Using an IoC container to build your object graph for you reduces complexity a ton and pushes it out into one-time configuration. I simply say "create me a 'Foo'" and it figures out what's needed to build one.
Some people use the IoC containers for much more infrastructure, which is fine for advanced scenarios but in those cases I agree it can obfuscate and make code hard to read and debug for new devs.
Here is why. The project is called IOC-with-Ninject. You can download and run it with Visual Studio. This example uses Ninject but ALL the 'new' statements are in one location and you can completely change how your application runs by changing which bind module to use. The example is set up so you can bind to a mocked version of the services or the real version. In small projects that may not matter, but in big projects it's a big deal.
Just to be clear, advantages as I see them: 1) ALL new statements in one location at root of code. 2) Totally re-factor code with one change. 3) Extra points for 'cool factor' 'cause it's... well: cool. :p