Category: Principles
Type: Systems design principle
Origin: Robert C. Martin, Engineering Notebook, C++ Report, 1996
Also known as: DIP; depend on abstractions, not concretions; the D in SOLID
Type: Systems design principle
Origin: Robert C. Martin, Engineering Notebook, C++ Report, 1996
Also known as: DIP; depend on abstractions, not concretions; the D in SOLID
Quick Answer — The Dependency Inversion Principle says high-level policy must not depend on low-level details; both should depend on abstractions, and details should depend on those abstractions. Robert C. Martin named it in a 1996 C++ Report column after a copy program that could not change printers without rewriting the policy. The practical test is simple: if swapping a vendor, device, or person forces you to rewrite the rule, the rule depended on the wrong thing.
What is the Dependency Inversion Principle?
The Dependency Inversion Principle is a design rule that a policy module should depend on an abstraction it owns, not on the concrete mechanism that happens to carry the policy out today.High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.That is not a plea for more interfaces. It is a rule about who is allowed to force a rewrite. Policy is the reason the system exists: copy this, pay that, admit these students. Details are keyboards, printers, Oracle drivers, and the cousin who currently drives the bus. If policy imports the detail, every swap of the detail reopens the policy. The everyday picture is a wall socket. A kettle is not soldered into the plaster. The house publishes a socket. Kettles, lamps, and phone chargers plug in. If you hard-wire the kettle, a broken element means ripping the wall. The Open-Closed Principle wants new kettles without editing the house. This principle says which way the wire may run: the house does not depend on a brand of kettle. The kettle depends on the socket the house already defined. In code, a
Copy() function that calls ReadKeyboard() and WritePrinter() by name does the same solder job. A new disk writer then forces an if into the policy, and the next device another if. The bruise is rigidity: the important module cannot be reused, and it cannot be tested, without dragging the hardware along. Separation of concerns splits the jobs. This principle splits the direction of the source dependency.
Dependency Inversion Principle in 3 Depths
- Beginner: Do not solder the lamp to the house. Publish a socket. Then a different lamp can plug in without rewriting the wiring diagram.
- Practitioner: Let policy depend on a port it defines. Put the vendor, file, or person behind that port. If a change of brand edits the rule, the arrow still points the wrong way.
- Advanced: Runtime still flows from policy into details. What inverts is the source-code arrow. The high-level module owns the abstraction, so details plug inward. A wrapper owned by the vendor is not inversion. It is the old dependency with an extra name.
Origin
The Dependency Inversion Principle began as a coupling diagnosis in object-oriented C++, not as a slogan about dependency-injection frameworks. Robert C. Martin stated it in The Dependency Inversion Principle, the third of his Engineering Notebook columns for C++ Report (May 1996). He had already argued, in Object Oriented Design Quality Metrics: an analysis of dependencies (1994), that the direction of source dependencies decides whether a design goes rigid. The 1996 column gave the rule a name. Traditional structured design, he wrote, tends to make high-level modules depend on low-level ones, and abstractions depend on details. He called the repair an inversion of that habit. The paper’s working wound is aCopy program on a machine with no device-independent I/O. The policy loops: read a character from the keyboard, write it to the printer. Copy therefore depends on ReadKeyboard and WritePrinter. Add a disk file, and the policy sprouts a boolean and an if. Martin’s fix is two abstractions, Reader and Writer, owned beside Copy. Keyboard and printer implement them. The dependencies invert: details depend on the policy’s sockets. He notes that C’s stdio.h—getchar and putchar—is the same shape without classes.
Agile Software Development: Principles, Patterns, and Practices (Prentice Hall, 2003) restates the two clauses and adds the Button/Lamp picture. A button that names Lamp cannot later switch a motor. A ButtonClient or Switchable socket lets the lamp plug in. Around 2004, Michael Feathers arranged Martin’s “first five” principles into the SOLID mnemonic. The Dependency Inversion Principle is the “D.”
In Clean Architecture (Prentice Hall, 2017) Martin widened the same arrow into the Dependency Rule: source dependencies point inward, toward policy. Martin Fowler’s Inversion of Control Containers and the Dependency Injection Pattern (23 January 2004) named a wiring technique—constructor, setter, and interface injection. That article is about how an object receives a neighbor. It is not a rename of this principle. The Interface Segregation Principle was the next C++ Report column, and asks a different question: once you have a socket, is it too wide?
Key Points
The Dependency Inversion Principle earns its keep when policy must outlive the current mechanism. It is not a ban on calling concrete code. It is a rule about which names the important module is not allowed to mention.1
Invert the source arrow, not the runtime call
At run time, the button still tells the lamp to turn on. What changes is compile-time knowledge. Policy must not import, subclass, or construct the detail. The detail must implement a type the policy already defined. If the high-level file still names
OracleDriver, the arrow did not invert. You added a hop.2
The high-level module owns the socket
An interface living in the vendor’s package is the vendor’s face, not yours. Martin’s point is ownership:
Copy specifies Reader and Writer. Keyboard and printer conform. A school that writes “must drive our Saturday route” owns the role. A school that writes “must be Cousin Wei’s van” has given the cousin the socket. Liskov substitution then asks whether the next van can actually stand in.3
Do not let details leak through the abstraction
A
Database port that returns OracleResultSet, or a “bus operator” contract that requires one company’s radio protocol, is a socket with the old plug glued on. Callers still compile against the detail. Keep vendor types, file formats, and person-specific habits behind the port. The Single Responsibility Principle keeps policy from growing extra reasons to change. This principle keeps those extra reasons from being imported.4
Do not invert what does not vary
String, a stable language list, and a one-off script that will die with its file do not need a port. YAGNI applies: invent the socket when a second mechanism is real, or when tests must replace the first. An interface per class is ceremony. The cost is navigation, and a fake sense that the design is already flexible.Applications
Use the Dependency Inversion Principle when the rule should survive a change of tool, vendor, or person. Do not use it to wrap every object you already trust.Put a port between the rule and the I/O
Billing should depend on
Clock and Mailer, not on System.now and last year’s SMTP class. Write the port next to the policy. Adapt the vendor behind it. When the mail provider changes, the invoice rules do not reopen.Hire the role, then plug a person in
A weekend roster that names one uncle’s phone number is soldered. Write the duties: licensed, insured, Saturday 7 a.m. The named person is one implementer. A substitute can plug in without rewriting the school’s policy. That is this principle applied to a job, not only to a class.
Publish a public socket, not a branded appliance
Wall outlets, USB, and a city form that accepts “any licensed electrician” are the same cut. Citizens should not rebuild the house to change a kettle. If a public service hard-codes one vendor’s portal, every procurement cycle rewrites the service. Standardize the socket; let brands compete behind it.
Replace the real mechanism with a fake in tests
Early-career code that
news a live database cannot be checked on a train. Depend on a port, pass a fake that returns known rows, and keep the policy tests free of the network. You are not “doing Spring.” You are making the important module runnable without its current hardware.Case Study
The numbered public window onto the Dependency Inversion Principle is Java Database Connectivity (JDBC)—not a claim that one database API is the whole of architecture. Sun specified JDBC in January 1997 and shipped it with JDK 1.1 on 19 February 1997. The API is two layers on purpose. Application code talks tojava.sql.Connection, Statement, and ResultSet. Vendors implement java.sql.Driver. DriverManager.getConnection looks up a driver that can handle the URL. A payroll module therefore compiles against java.sql, not against oracle.jdbc or a MySQL client. Swap the jar, keep the policy. That is Martin’s inverted arrow in a platform library: high-level code and low-level drivers both depend on the same abstractions, and the details (the drivers) depend on those abstractions.
The 1996 JDBC draft already split “API for application writers” from “JDBC Driver API.” Java SE 6 (11 December 2006) added JDBC 4.0 service loading: a driver ships META-INF/services/java.sql.Driver and the platform can find it without Class.forName. As of Java SE 26 (2026), the java.sql module still exports those interfaces. OpenJDK’s Connection type is marked @since 1.1. The inversion has outlived several generations of databases.
Boundary note: JDBC does not make SQL portable. A policy that embeds Oracle outer-join syntax still depends on a detail, even if every type is java.sql. DriverManager itself is a concrete locator; later teaching prefers DataSource. The lesson for new design is the 1997 split of policy from driver, not the claim that a standard API erases dialect. If the next database still forces you to rewrite queries, you inverted the types and left the language soldered.
Boundaries and Failure Modes
The Dependency Inversion Principle fails when the detail is stable and local. WrappingString, Math, or a one-file script behind IString adds types without buying a second implementation. The socket is a cost. Pay it where a second mechanism, a test double, or a vendor swap is real.
It also fails when the abstraction is owned by the detail. An IOracleConnection in the driver package, or a “standard” form that still requires one company’s attachment layout, leaves policy chasing the vendor. Inversion is not the presence of an interface. It is the direction of ownership.
The common misuse is treating a dependency-injection container as the principle. A container can inject a concrete OracleRepository into a concrete PayrollService that still imports Oracle types. The wiring is inverted. The dependency is not. Another misuse is an interface per class, then a maze of types that still change as a set. Law of Demeter still applies after inversion: talking to a socket does not license digging through the object you were handed to reach its inner vendor.
Common Misconceptions
The English name collides with “dependency injection,” with “every class needs an interface,” and with the Hollywood line “don’t call us, we’ll call you.”The Dependency Inversion Principle is the same as dependency injection
The Dependency Inversion Principle is the same as dependency injection
Injection is a delivery method: a constructor argument, a setter, or a framework hands you the neighbor. Inversion is a dependency rule: that neighbor is typed as a policy-owned abstraction, not as a vendor class. You can inject a concrete Oracle helper and still violate the principle. You can construct a
KeyboardReader in main and still satisfy it, because Copy never named the keyboard.The Dependency Inversion Principle means every class gets an interface
The Dependency Inversion Principle means every class gets an interface
Martin inverted
Copy against Reader and Writer because those mechanisms were expected to change. He did not demand a port in front of every integer. Stable language types, private helpers, and a module with one concrete life do not earn a socket. An interface whose only implementer will always be itself is a hat on a hat.The Dependency Inversion Principle is the Hollywood principle
The Dependency Inversion Principle is the Hollywood principle
“Don’t call us, we’ll call you” inverts who starts the conversation—a framework calls your plugin. This principle inverts which names a source file is allowed to mention. Event loops, callbacks, and containers can help. They can also call concrete details. Owning the socket is the test, not whether a framework rang first.
Related Concepts
These pages sit next to the same problem: how to keep the important rule from being rewritten every time the current tool, vendor, or person changes.Open-Closed Principle
New details should plug in without editing policy. This principle says the plug must point at an abstraction the policy owns.
Liskov Substitution Principle
A plugged-in detail must honor the socket. A lamp that cannot turn off is not a substitute, even if it implements
Switchable.Interface Segregation Principle
Once you have a socket, do not make callers depend on holes they will never use. Inversion without segregation is a fat plug.
Single Responsibility Principle
Policy should have one reason to change. Inversion stops extra reasons from being imported as concrete names.
Separation of Concerns
Keep policy and mechanism apart. This principle sets the direction of the remaining dependency between them.
Law of Demeter
Talk to your immediate socket. Do not reach through it into the vendor’s inner objects.