iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
The Dependency Inversion Principle (DIP), the “D” in SOLID, says that high-level policy and low-level implementation should both depend on abstractions—and that those abstractions should not depend on implementation details. In practice, business logic should describe the capability it needs in domain terms, while infrastructure supplies an implementation of that contract.
What does the Dependency Inversion Principle mean?
DIP has two parts:
- High-level modules should not depend on low-level modules. Both should depend on abstractions. High-level modules contain policy or business rules; low-level modules handle details such as databases or external services.
- Abstractions should not depend on details. Details should depend on abstractions. The contract expresses what the policy needs, and implementation code conforms to that contract.
The key is not simply adding an interface. It is choosing a contract at the right level, so policy code does not have to know about an infrastructure mechanism it does not need.
How does DIP differ from dependency injection?
DIP is a design principle: it concerns the abstraction that code depends on and the direction of the dependency. Dependency injection (DI) is a way to provide an object with another object it needs. A constructor parameter, setter, method argument, or container can provide that dependency, but injection by itself does not make the dependency a well-chosen abstraction.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Inversion of control (IoC) is related but distinct: it describes who initiates an interaction. Framework callbacks are one example. A design can use DI without following DIP if high-level code is still coupled to a low-level mechanism.
#1 Best Overall
Why a domain-level contract matters
Martin Fowler illustrates DIP with a Monopoly game. Suppose a game object needs to read its board. It could depend directly on a JDBC connection and SQL statement. Passing that connection into the game object would be dependency injection, but the game would still know about a database mechanism that is below the level of its domain.
A BoardRepository abstraction describes what the game needs: access to board data. A database-backed implementation can provide that capability. The game depends on the domain-relevant contract, while the infrastructure implementation depends on the contract it fulfills. As Fowler puts it, “DIP is about the shape of the object upon which the code depends.”
Rank #2
A small example of the dependency direction
This illustrative Java-style pseudocode shows the relationship without relying on a particular framework:
Free tools Windows power users keep installed
One-click scans. No signup required.
interface BoardRepository {
Board loadBoard();
}
class MonopolyGame {
private final BoardRepository boards;
MonopolyGame(BoardRepository boards) {
this.boards = boards;
}
void start() {
Board board = boards.loadBoard();
// Apply game rules using the board.
}
}
class SqlBoardRepository implements BoardRepository {
public Board loadBoard() {
// Read and map the board from a database.
}
}
MonopolyGame relies on the capability represented by BoardRepository; it does not issue SQL or know how the board is stored. SqlBoardRepository supplies the infrastructure detail. Application startup can construct the game with the chosen implementation, keeping the policy-facing code unaware of that choice.
How to apply DIP without overengineering
- Start with a use case. Identify the capability the higher-level policy actually needs.
- Name the contract in domain language. Describe that capability rather than exposing a low-level technology API.
- Keep the contract focused. Include operations needed by current use cases; avoid an oversized API with unrelated methods.
- Make details conform to the contract. Infrastructure adapters implement the abstraction rather than making policy code depend on their mechanisms.
- Keep wiring visible. Choose and provide concrete implementations where the application is assembled, so it is clear how the dependency is supplied.
Do not create interfaces merely because a class has one implementation today, or design for hypothetical implementations without a real need. An abstraction can technically be an interface and still sit at the wrong level: a broad API such as JDBC may abstract database access while exposing details the consuming domain should not manage. Unnecessary factoring adds work, and an overly broad contract makes consumers aware of operations they do not need.
A practical review checklist
- Domain fit: Does the abstraction describe the consuming policy’s need, or the implementation’s mechanism?
- Dependency direction: Does policy code depend on the contract while implementation details conform to it?
- Surface area: Does the contract contain only operations needed by current use cases?
- Wiring: Is it clear where the concrete implementation is selected and provided?
Where the principle came from
Historical accounts distinguish naming from earlier introduction. Old Dominion University’s SOLID teaching material says Robert Martin named DIP in 1996. Fowler writes that Martin introduced him to the principle around 1994. Those statements do not establish a single exact first-publication date.
For broader context, TU Delft lists Robert C. Martin’s Agile Software Development: Principles, Patterns, and Practices (2002) as further reading. It covers software design and development broadly; it is not a dedicated DIP manual and is not necessary to understand the principle.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

