Overview
This page is the atomic definition. The broader principles live at general-principles.
Definition
Dependency injection (DI) is a design pattern where a component receives its dependencies (clients, repositories, loggers, config) from the outside instead of constructing them inside its own body. Injection happens through a constructor parameter, a function argument, or a framework’s wiring. DI replaces direct instantiation with indirection, which lets the caller swap real dependencies for fakes during tests and reconfigure the wiring per environment. Frameworks like Spring, NestJS, and FastAPI provide DI containers; many codebases use plain constructor injection without a container.
When it applies
Use dependency injection whenever a component needs to be testable in isolation, deployable across environments, or composed with different implementations. Skip it for pure functions and small scripts where the indirection cost outweighs the benefit.
Example
# Without DI: hard to test.
def send_invoice(invoice):
smtp = SMTPClient(host="smtp.example.com")
smtp.send(invoice.email, render(invoice))
# With DI: pass the mailer in.
def send_invoice(invoice, mailer: Mailer):
mailer.send(invoice.email, render(invoice))Related concepts
- general-principles - the broader principles that include DI.
- testing - DI is what makes unit tests cheap to write.
- fastapi - FastAPI’s
Depends()is a built-in DI mechanism. - side-effect - DI makes side effects explicit and swappable.
- twelve-factor - the config and backing-services rules rely on DI.
Citing this term
See Dependency injection (llmbestpractices.com/glossary/dependency-injection).