I am working on my first project that’s using an IoC container heavily. Overall it’s been a very positive experience. However, we have learned some things have caused us pain in testing, bug fixing, and general code maintenance.
Separate component registration from application start-up
This is a constant source of problem on our project. If you don’t separate component registration from your component start-up path you often run into a chicken-and-egg problem. You may be resolving a component that depends on other components that haven’t yet been registered. This makes for a very brittle start-up path that is prone to breakage as you add dependencies to your components. Now the container that is supposed to decouple things is causing you to micromanage your component registration and start-up.
The solution is to split registration from component start-up. This makes perfect sense to me now, but wasn’t so obvious when we started the project. Lesson learned!
Be careful with a global service locator
We went quite a while without using a global service locator (essentially a singleton instance of the container) but eventually found that we needed it. This might have been avoided with better design-fu but we couldn’t think of a better alternative at the time.
What we found was that the global container made things difficult to test. This became especially painful when we needed to push mock objects into our container and than manually clean up the registrations to replace them with the production components that other tests might expect. I’d be interested in hearing if you have a way to solve this problem, and if so, how.
Use a Full-Featured Container
When we started the project we had intended to use Enterprise Library for some features. EntLib has Unity integration so we settled on using Unity as our IoC container by default. The container itself has served us extremely well. What we’ve found lacking in the container though is it’s supporting infrastructure features. A container like StructureMap comes with alot of nice features that aren’t core IoC features. For example, it reduces the “ceremony” (as Jeremy D. Miller would say) of registering components by providing convention-based component registration. StructureMap also provides detailed diagnostics that help you figure out what’s wrong with your component registrations if things don’t work.
That summarizes the biggest points that we’ve learned so far. I’d be interested to hear some “gotchas” that you’ve learned from using an IoC container “in anger”.