Card 03/ 09

ConceptDifficulty: Intermediate2 min

Dependency Injection: Handing an Object What It Needs

Pass the database in through the constructor instead of creating it inside.

Dependency injection means giving an object the things it depends on, usually as constructor parameters, instead of letting it create them. It is the most common way to apply the dependency inversion principle, and this card shows how it works and how it differs from inversion itself.

A dependency is any object a class needs to do its work, such as a database or a mailer. To inject it is to pass it in from outside. Whoever builds the object decides which implementation it gets: the application's start-up code passes the real database, and a test passes a fake.

Creating a dependency, or receiving it

Created insideThe class chooses its own detail

self.database = MySQLDatabase(url) in the constructor. Every ReminderService talks to MySQL, and a test cannot change that without patching the module.

InjectedThe caller chooses

def __init__(self, users: UserSource). The service accepts anything with email_for. Production passes a MySQL implementation; a test passes a fake.

Constructor injection is the usual form because it makes the dependency visible: you cannot create the object without supplying it, and the parameter list documents what the class needs. Two other forms exist. Setter injection assigns the dependency after creation, which allows an object to exist half-configured. Parameter injection passes the dependency to the single method that needs it, which suits a dependency used in one place.

Injection and inversion are related but not the same. Inversion is about the direction of dependencies: the policy depends on an interface it owns. Injection is a technique for supplying objects. You can inject a concrete MySQLDatabase, typed as MySQLDatabase, and the service still depends on MySQL; the arrow has not turned round. Inversion needs the parameter's type to be an abstraction the policy owns. Injection is what makes that abstraction useful, by letting someone hand over an implementation.

Martin Fowler's 2004 article "Inversion of Control Containers and the Dependency Injection pattern" gave injection its name, to separate it from the broader term "inversion of control".