Dependency Injection Demystified

I’m building a robot to make breakfast.

def make_breakfast():
fridge = get_reference_to_fridge()
eggs = fridge.get_eggs(number_of_eggs=2)
fried_eggs = fry(eggs, over_easy)
cabinet = get_reference_to_cabinet()
plate = cabinet.get_plate()
add(fried_eggs, plate)

return plate

This is OK, but I realize my robot needs lots and lots of practice, and I don’t like wasting all my nice eggs and getting all my plates dirty. So, while my robot is still learning how to cook, I want to specify that it uses paper plates and some crappy expired eggs I fished out of the grocery store dumpster.

I need to change make_breakfast so that I can specify the eggs and plates when I call the function.

def make_breakfast(eggs, plate):
fried_eggs = fry(eggs, over_easy)
add(fried_eggs, plate)
return plate

Now when I want my robot to just practice making breakfast, I’ll do this:

make_breakfast(rotten_eggs, paper_plates)

And later, once testing is complete, I’ll do this instead:


The big idea is very simple: the make_breakfast function depends on eggs and a plate. In the very first version, the function got those eggs and the plate itself.

In the later versions, the eggs and the plate are passed in as inputs to the function. This makes it easier to tweak what kinds of inputs are used.

This article beats the topic of dependency injection into a pulp, but the example above illustrates everything I understand about the topic.

In the programming world, handing my robot the rotten eggs and paper plates might correspond to using mock objects during automated tests. Furthermore, it isn’t absolutely necessary to pass in objects as parameters. Instead you could imagine that my make_breakfast function queries a database, or an XML file, or some command-line switches, or anything else that allows me to specify at run time where to obtain the objects that provide the required capabilities.

Update: Somebody already wrote an article with the exact same title as this more than a year ago. That article is very thorough and argues the same point that I want to make: dependency injection is an overblown term for a good idea.

Another update: Based on a conversation with Aaron Oliver, I changed the second example so that I pass in the eggs and plate directly, rather than pass in an object that provides these resources.