I start this post asking myself what Dependency Injection is and how I can best apply it to my work as a development. It's all the rage in Java and C# camps and the term is usually huddled next to words like "framework", "Inversion of Control" and other fancy terminology. I'm going to take a stab at answering this question with some help from a Java nerd.
image from jenthompsonphotography.com
I fell upon an excellent post by Misko Hevery where he describes how we should treat the “new” operator. He inadvertently explained Dependency Injection in a really clear and simple way using a House and a Kitchen object.
I’ve had a hard time with Dependency Injection as an underlying concept, however Hevery manages to distil the goal of DI extremely eloquently: “we are mixing the concern of application instantiation with concern of application logic.”
Simply put, a class that has “new” inside it is not only building other objects, but also containing behaviour. His answer is, of course, yet-another-class-and-design-pattern:
The (Factory) ApplicationBuilder:
class ApplicationBuilder { House build() { return new House(new Kitchen( new Sink(), new Dishwasher(), new Refrigerator()) ); } }
The consuming code, or the code that is going to be using this, in PHP would look something like this:
$applicationBuilder = new ApplicationBuilder(); $myNewHouse = $applicationBuilder->build();
While Hevery’s goals are test-driven, I think this practice can be applied to even a non-test-driven workflow. In the code above, instantiation and bevahiour are separated. I’m still working through the example, however I’m guessing a house with an IKEA kitchen could be built with construction of a different Kitchen object entirely (either implementing an IKitchen interface or inheriting from a Kitchen base class):
$applicationBuilder = new ApplicationBuilder(); $myNewHouse = $applicationBuilder->buildHouseWithCustomKitchen($IKEAKitchen);
My only gripe about all this is that this approach to development leads to pretty large object graphs. Simple projects that could be accomplished with less than 10 or so files could span across several dozen.
A good designer can pick the right tool for the job. For a large project where conditional code (lots of if and switch statements), Dependency Injection can minimize the complexity of through abstraction. In this example, our applicationBuilder doesn't CARE about what kind of kitchen is injected, just that it can perform the necessary functions.
The flip side of this form of abstraction is the cost associated with indirection. Because we've moved our complicated kitchen-building code into a whole bunch of little Kitchen-inheriting (or IKitchen-implementing) classes, we now can have a plethora of Kitchens without changing any code in our Application Builder, we simply need to create a new kitchen that meets the criteria for injection.
{ 3 comments… read them below or add one }
HAPPY BIRTHDAY!!!!!!!!!!!!!!!
I was a bit confused until I went and looked up DI, and found that it doesn’t actually have anything to do with the factory, but with the fact that you’re passing in the components of the Kitchen as arguments to its constructor. In effect, the caller, the outer part of the program, is controlling the inner behaviour of the Kitchen while letting the callee (Kitchen) handle the middle parts.
What’s interesting is that this sort of division of control is found all over the place, not just for the composition of objects. For example, ‘map’ in functional programming languages takes a function and a list, and returns a list of the function applied to each of the elements of the old list.
map(add1, list(1, 2, 3)) == list(2, 3, 4), where add1 is a function which returns its argument plus 1
In this case the caller handles what behaviour is used inside of map, while the map function itself handles looping and constructing the new list.
It seems like a different concept, but it’s really the same idea. What’s powerful is the fact that behaviour itself, though it may be represented as a function or as an object, can be held in a variable and passed around your program.
Wait a moment, this isn’t relationship advice?
Baah.