So, I finally got an implementation of an IoC Container (Castle Windsor) set up and being used in a production environment…. Based on the whole settings things up for mocking, it became very clear why they were needed!
On a current project, I’d set up and gone though writing tests as I went along. It was a colleague’s task to write a bunch of integration tests. (The question of how many full, top-to-bottom integration tests are actually needed is an interesting, but different question… regardless, they are well understood and trusted) It turns out that all of these interfaces and the tons of newing up required for the dependency injection got to be pretty painful, and what’s worse, confusing and unclear. Also, as I was refining things, I continued to refactor what was there, so the constructor signatures were changing… messing up AL those integration tests. I think if he were less nice, he would have said “WHY do you have to make this so confusing??”
Exactly the situation IoC containers were made for. And I think I got it all set up in about an hour, from download to finish! Which is a few hours less than I’d expected. I couldn’t quite get my create down to a single line a) because I was dealing with VB.Net, an irritatingly verbose, hard-to-scan language, but more importantly b) I had to pass in a configured object in to one of my objects, and then pass THAT on to the constructor of object I was really trying to get. Previously, this chain was hidden among the plethora of newed-up stuff. Once the container was in place, all I had were these special items, right after each other-this chain of dependencies on the configured object was very clear… the cluttering vanilla dependencies were out of sight. I consider this a huge, and unexpected benefit. If I need to change my constructors to break things up more (I have a few places in mind) then I won’t break these complex integration tests. My mocked out tests, sure… but they are each restricted in what they touch anyway, so the trouble there is much less.
I know, these were tests, and people often don’t use containers for tests. However, because of their being integration tests, it felt appropriate.
An interesting point is that this is all going to end up being accessed through a single webservice, so the “live” newing up is only going to be in one place-so less *need* of a container for live. This is just as well, because another team is doing the maintenance, and this way the unfamiliar stuff isn’t in actual live stuff that’ll could freak them out if something happens with it on live. Same reason we went with VB… Anyway, even if we don’t use it on “live” code, Windsor will still save us time.
Of note is really how all these things sort of come together as a package- DI, mocking, IoC. You want mocking, you do Dependency Injection, probably Constructor Injection. You do much of that, and you’ll find yourself wanting something to magic everything up… thus your Inversion of Control Container. I’d looked at containers a few months back (I’d heard them mentioned a LOT, and thought I should look into them), but I didn’t quite get a grasp of when or why you’d ever use them in practice. I changed how I worked, and it became obvious.