Software Architecture & Design Principles

Dependency Inversion & Injection

Three related but distinct ideas get conflated under "DI": the Dependency Inversion Principle (depend on abstractions), Dependency Injection (a technique for supplying those abstractions from outside), and an IoC container (one optional tool for wiring injections automatically). You can have the first two without ever touching a container.
  • DIP: high-level modules should not depend on low-level modules — both should depend on abstractions
  • Dependency Injection: a class receives its collaborators (via constructor, ideally) rather than constructing them itself
  • An IoC container automates wiring injections but is a convenience, not a requirement — "poor man's DI" (plain constructors) works fine at small scale
  • Constructor injection over field/setter injection: dependencies become explicit, final, and impossible to forget
  • DI is what makes swapping a real collaborator for a test double trivial — the core enabler behind Testing Philosophy
Inverted: the high-level class depends on an interface it owns
// Before: OrderService is welded to a concrete, volatile detail.
class OrderService {
    private final SmtpMailer mailer = new SmtpMailer();  // hard-coded, untestable
    void placeOrder(Order o) { /* ... */ mailer.send(o.confirmationEmail()); }
}

// After: depends on an abstraction; the concrete choice is supplied from outside.
interface Notifier { void send(String message); }

class OrderService {
    private final Notifier notifier;
    OrderService(Notifier notifier) { this.notifier = notifier; }   // constructor injection
    void placeOrder(Order o) { /* ... */ notifier.send(o.confirmationEmail()); }
}
Three ideas, one abbreviation
TermWhat it isRequired?
DIPA design principle: depend on abstractions, not concretionsFoundational — the goal
Dependency InjectionA technique: pass collaborators in instead of constructing themThe mechanism — usually via constructor
IoC ContainerA tool that constructs the object graph and injects automaticallyOptional — helpful at scale, unnecessary for a small app
Sources
  • Clean ArchitectureCh. 11 — DIP; Ch. 25 — Layers and Boundaries