Or “My Most Recent Moment of Feeling Like an Idiot“
The first Friday in May, I attended my first professional conference ever (was that an exhilarating and terrifying concept to wrap my head around), StirTrek here in Columbus. I could go on about the conference as a whole, but what I actually want to get to is one specific three minutes or so in the first session of the day.
I sat in on Jeremy Clark‘s DI Why: Getting a Grip on Dependency Injection and enjoyed every second of the talk–if you get the chance to see this fellow, I recommend it. He did an awesome job validating what I did understand about dependency injection as a concept, and filled in some crucial gaps that (as he mentioned) left me both frustrated and in awe at the magical nature of DI.
Including property injection, which I’d been using since my C# II course at CSCC. But see, literally NOTHING was explained about dependency injection–we were copying a pattern laid out by a guy the instructors conned into recording some videos live coding a project. All we were able to glean from this video was “We really should be dealing with something like Ninject but your poor students don’t need that level of complexity.”
That’s a sentence that ONLY makes sense now, a year later, having fought with Castle Windsor and constructor injection patterns. I didn’t even know enough to ask “What is going on here?”
But I digress–the point is Jeremy made me feel like an idiot to the degree I actually groaned out loud in the theater (waking the guy next to me, but that’s another story).
If you have NO idea what I’m talking about with property injection, let me show you a teeny bit of code:
My Scores and Evaluations properties are domain level services that have all the business logic I need for those entities. I call for the properties themselves to be interfaces, and in my getter I set the backing field to a new, concrete implementation of the interface if the field hasn’t been set yet.
I figured out on my own, after reading The Art of Unit Testing by Roy Osherove, this was probably about unit testing–being able to swap in a mock service class and thus isolate things to be testable. (Our project in that class was designed with TDD in mind, but that was a step too far for the CSCI department at the time). It’s a pattern I’ve followed in my personal stuff ever since, since it worked and I was able to implement unit tests pretty easily.
So, where’s the part where I feel like an idiot, if I already grasped (mostly, sorta) how this works?
The Ah-Ha Moment:
Let me show you another piece of code and I think the problem will be immediately clear.
In my test project, I have a service factory that spins up ScoreService classes all day long. And it passes in the mock ScoreInteractor classes via constructor injection. Nowhere in my code base, prior to StirTrek, do I actually set a property injected dependency via the property’s setter.
Talk about light dawning over marble head…
Wrapping It All Up:
I mean, there’s nothing inherently wrong with passing in my mock classes this way–I have fairly dry code, the right dependency is injected at the right time, my tests pass, and the application actually does what I expect it to do in the production environment.
And yet. There’s an extra constructor. Which opens the door to so much complexity no one has any time for. This may not be a huge deal in my 4-controller, 3-entity hobby application but as soon as I saw Jeremy set his dependencies via the properties? I immediately started to have visions of how this can help me streamline recent code in the solution at work.
Imagine the examples below with 6 or 7 dependencies, rather than just 1 or 2 and you might start to see why I was getting excited.