2.2.8Design Principles

SOLID — Dependency Inversion Principle

1,897 words9 min readdifficulty · medium3 backlinks

WHAT is the Dependency Inversion Principle?

WHY does it matter?

HOW: deriving it from first principles

Let's derive the principle by reasoning about change.

Step 1 — Observe the natural coupling. A normal call graph:

OrderService → calls → MySqlOrderDb (concrete)

Why this step? We want to see where the dependency arrow points by default: high-level depends on a concrete detail.

Step 2 — Ask: which part is more valuable / more stable? OrderService (policy) is the business asset; MySqlOrderDb is a swappable mechanism.

Why this step? DIP is fundamentally about protecting the stable thing from the volatile thing.

Step 3 — Insert an abstraction the high-level module owns. Define OrderRepository (interface). Now:

OrderServiceOrderRepository (interface) ← MySqlOrderDb (implements)

Why this step? Both modules now depend on the abstraction; the concrete detail's arrow has been inverted to point up.

Step 4 — Supply the concrete via injection. Hand the concrete object in through the constructor (Dependency Injection is the common delivery mechanism).

Why this step? The high-level module must never new the concrete — otherwise the source-code dependency sneaks back.

Figure — SOLID — Dependency Inversion Principle
Recall Feynman: explain to a 12-year-old

You have a toy robot. Instead of gluing one specific battery inside, you give it a battery slot of a standard size. Now you can put in any battery — rechargeable, regular, even a solar pack — as long as it fits the slot. The robot only knows "a thing that fits the slot," not the exact battery. So you can change batteries forever without ever opening up and rebuilding the robot. The "slot shape" is the abstraction; the robot is your important code; the batteries are the swappable details.

Active Recall

What are the two clauses of the Dependency Inversion Principle?
(1) High-level and low-level modules should both depend on abstractions, not each other. (2) Abstractions should not depend on details; details should depend on abstractions.
What does "inversion" refer to in DIP?
Flipping the dependency arrow: instead of high-level code depending on a concrete low-level class, both depend on an abstraction the high-level module owns — so the detail's arrow points UP.
Difference between DIP and Dependency Injection?
DIP is a design goal (depend on abstractions); DI is a technique for delivering the dependency. You can use DI yet still inject a concrete and violate DIP.
Which letter of SOLID is DIP?
The "D" (last one).
Where should the abstraction (interface) ideally live?
With/near the high-level policy module that owns it, so the low-level detail package depends on the policy package — making the dependency truly inverted.
Define instability I in terms of couplings.
I = Ce / (Ca + Ce); I=0 is maximally stable (nothing it depends on), I=1 is maximally unstable.
Why shouldn't you wrap every class in an interface?
Abstractions add indirection cost; apply DIP at volatile boundaries (DB, network, UI, 3rd-party) — 80/20, not everywhere.
What practical benefit does DIP give for testing?
You can inject a fake/mock implementation of the abstraction, testing business logic without real DB/email/network.

Connections

Concept Map

rule 1

rule 2

depends on

implements

achieved by

flips arrow of

supplies concrete to

must not new

ensures arrow

enables

Dependency Inversion Principle

High-level Module - policy

Low-level Module - detail

Abstraction - interface

Inversion - flip arrow

Dependency Injection

Points toward stability

Testable in isolation

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, Dependency Inversion Principle ka core idea simple hai: tumhara important business logic (high-level code) kabhi bhi seedha kisi concrete chhoti cheez (jaise MySQL database ya EmailSender) par depend nahi karna chahiye. Dono ko ek beech ke abstraction (interface) par depend karna chahiye. Socho ek electric socket — tumhara charger sirf socket ki shape par bharosa karta hai, power plant kaun sa hai isse matlab nahi. Wahi socket ki shape yahan "interface" hai.

"Inversion" ka matlab hai dependency ka arrow ulta karna. Normally OrderService apne andar new MySqlDb() likh deta hai — yaani policy detail par depend karti hai (arrow neeche). DIP bolta hai: ek OrderRepository interface banao, OrderService usi interface ko jaane, aur MySqlDb us interface ko implement kare. Ab detail ka arrow upar point karta hai. Bas yahi inversion hai.

Iska faayda? Agar kal database badalna ho ya Email ki jagah SMS bhejna ho, toh tumhe apne core logic ko chhuna hi nahi padega — bas ek nayi class bana ke inject kar do. Aur testing mein ek nakli (fake/mock) implementation pass kar ke bina real DB ke test ho jata hai. Ek important baat: DIP aur Dependency Injection same nahi hai — DIP ek goal hai (abstraction par depend karo), DI ek tarika hai (object ko bahar se pass karna). Aur har class ko interface mein mat lapeto — sirf un jagah jahan change hone ke chance zyada hain (DB, network, UI). Yahi 80/20 wisdom hai.

Go deeper — visual, from zero

Test yourself — Design Principles

Connections