Dependency Inversion Principle
The dependency inversion principle makes high-level policy depend on abstractions it owns, and low-level details depend on those same abstractions, so that neither knows the other concrete type.
Definition
The dependency inversion principle states that high-level modules should not depend on low-level modules; both should depend on abstractions, and the abstractions should be owned by the high-level policy, so that the policy is reusable across detail implementations and the details are substitutable.
Context and scope
Applied in layered architecture, hexagonal architecture, plugin systems, and any design where the business rule must outlive the infrastructure choice.
Common misconceptions
- DIP is just dependency injection — DI is the mechanism that wires dependencies; DIP is the design principle that decides which direction the abstraction lives
- Every dependency should be inverted — inverting infrastructure is usually right; inverting value objects and domain primitives adds indirection with no benefit
Anti-patterns
- Owning the abstraction in the infrastructure layer, so the high-level policy still depends on the detail, just through an interface
- Inverting every dependency including stable domain primitives, producing a wall of interfaces for types that never change
Related concepts
Authoritative source
https://en.wikipedia.org/wiki/Dependency_inversion_principle
What it is
The dependency inversion principle states that high-level modules should not depend on low-level modules; both should depend on abstractions, and the abstractions should be owned by the high-level policy, so that the policy is reusable across detail implementations and the details are substitutable. Applied in layered architecture, hexagonal architecture, plugin systems, and any design where the business rule must outlive the infrastructure choice. The organizing principle is which decisions are hard to reverse and should be made once, versus which are easy to reverse and should be deferred.
How it works
Boundaries are drawn along axes of change: things that change together are colocated, things that change independently are separated by interfaces whose contracts are explicit and versioned. Dependencies point toward stability — domain logic depends on abstractions, infrastructure depends on domain, never the reverse. The structure makes the system’s intent legible without reading every module.
When to choose and pitfalls
Choose this structure when the system will outlive its first deployment and face requirements you cannot now predict. The pitfall is premature abstraction — adding indirection for a flexibility that never materializes, paying its complexity cost forever. The opposite pitfall is entangling concerns that later need to separate, forcing a rewrite instead of a refactor.