Wrap Up (4)
DIP in one honest sentence
The Dependency Inversion Principle says high-level policy must not depend on low-level details; both depend on abstractions. The part many wrap-ups miss is the ownership flip: the high-level module owns the interface vocabulary; details implement it. It is not enough to "introduce an interface" sitting next to the MySQL driver — the interface must be named and owned by the policy that needs the capability (e.g. OrderRepository in the domain package, implemented by JdbcOrderRepository in infrastructure).
// Wrong direction: policy imports MySQL types
class OrderService {
private final MySQLOrderDao dao = new MySQLOrderDao(); // detail owns the contract
}
// Inversion: policy owns OrderRepository; detail implements it
interface OrderRepository { Order find(Id id); } // owned by policy package
class OrderService {
private final OrderRepository repo; // depends on abstraction
OrderService(OrderRepository repo) { this.repo = repo; }
}
class JdbcOrderRepository implements OrderRepository { /* JDBC details */ }
The one place that is allowed to name concrete types is the composition root — the main method or DI-container configuration at the application's entry point, the only layer that wires new JdbcOrderRepository() into an OrderService. Every other module depends only on OrderRepository. If a new JdbcOrderRepository() appears anywhere but the composition root, dependency inversion is leaking.
Importance of DIP
By ensuring that high-level modules do not depend directly on low-level implementations, DIP allows for:
- Better Flexibility: Swap implementations (in-memory, Postgres, HTTP) without rewriting policy.
- Improved Maintainability: Detail volatility (driver upgrades, schema) stays outside the policy module.
- Enhanced Testing: Inject fakes that implement the policy-owned interface; no real DB required.
How DIP Relates to Other SOLID Principles
- SRP: DIP supports SRP by decoupling classes and minimizing dependencies so each class focuses on one responsibility while details are abstracted away.
- OCP: DIP helps achieve OCP by making modules open for extension (new implementers) but closed for modification of the policy.
- LSP: DIP complements LSP by ensuring implementations adhere to the policy-owned contract, making substitutions safe.
- ISP: DIP encourages designing smaller, specific interfaces owned by the client. High-level modules depend on minimal abstractions and avoid fat vendor APIs.
DIP Takeaways
| Principle | Smell | Fix | When it hurts |
|---|---|---|---|
| Dependency Inversion Principle | High-level modules new up concrete low-level classes; interface lives next to the detail (or is absent); tests require real databases, file systems, or HTTP clients. |
Depend on abstractions owned by the policy module; inject dependencies through constructors or factories. Details implement the policy's interface. | Inverting trivial, stable dependencies (e.g. StringUtils, language stdlib) adds indirection without benefit; invert only when the implementation carries volatility or needs test doubles. |
When applying DIP hurts
- Interface per trivial helper. Wrapping
Math.maxor a pure string util is noise. - Interfaces owned by the framework/detail package. If the "abstraction" is still a MySQL-shaped DAO interface, you inverted the name but not the dependency.
- Premature seams. A one-off script with a single known store does not need a repository interface yet.
DIP → Design Patterns
Patterns that make dependency inversion practical:
- Dependency Injection — Pass dependencies in rather than constructing them; the most common application of DIP.
- Factory / Abstract Factory — Centralizes object creation so clients depend on the product abstraction, not the concrete class.
- Strategy — The context depends on a strategy interface, not on any particular algorithm.
- Adapter — Allows a high-level module to depend on its own abstraction while still using a third-party implementation.
Follow-Up Drills
- Take a
OrderServicethat directly instantiatesMySQLRepository. Refactor so the service depends on a policy-owned abstraction and the repository is injected. Where does the interface live? - Explain why the
newkeyword inside business logic is often a DIP warning sign. - When is it acceptable for a high-level module to depend on a concrete utility class like
StringUtils? - Write a unit test for
OrderServiceusing an in-memory fake repository. What does DIP make possible here?
SOLID as a System
You have now seen all five principles. Notice how they reinforce one another:
- SRP gives you small, focused classes (one actor / reason to change).
- OCP lets you extend them without editing them.
- LSP keeps substitutions honest (area 16 ≠ 20 is the failure signal).
- ISP keeps interfaces minimal (compile-time honesty via role types).
- DIP points all dependencies toward policy-owned abstractions.
Next, apply them together in the OO Design Problems section. A principle you cannot apply under time pressure is not yet learned.
🤖 Don't fully get this? Learn it with Claude
Stuck on Wrap Up (4)? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Wrap Up (4)** (OO & Low-Level Design) and want to truly understand it. Explain Wrap Up (4) from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Wrap Up (4)** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Wrap Up (4)** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Wrap Up (4)** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.