This page builds every word and symbol the Dependency Inversion Principle uses — module, dependency, arrow direction, abstraction, interface, coupling, and the symbols Ca, Ce, I, A — from nothing. Everything you need is defined right here on this page; nothing is assumed from elsewhere.
Figure 1 — Two boxes side by side. The yellow box is policy (rarely changes, valuable); the blue box is mechanism (changes often, swappable). The figure fixes the colour code — yellow = high-level, blue = low-level — that every later diagram reuses so you can track a box by its colour alone.
We split modules into two kinds:
High-level module = the box holding policy — the rules, the "what to do". Rarely changes. Valuable.
Figure 2 — The pink solid arrow is the source-code dependency (who names whom); the white dashed arrow shows the tremor of change travelling backwards up it. The figure adds what words alone hide: these two arrows are separate ideas, and the danger is the tremor reaching your yellow policy box.
Figure 3 — The contract box sits above both. The yellow policy arrow and the blue detail arrow now both point UP at the shared shape. The independent insight: notice the blue arrow has physically reversed compared with Figure 2 — that reversal is literally the "inversion" the principle is named after.
The interface should be owned by / live near the high-level policy. That is what turns the low-level box's arrow upward — the detail now depends on the policy's contract, inverting the original arrow.
Words describe the flip; code proves it. Here is the before — policy welded to a detail:
// BEFORE — arrow points DOWN from policy to concrete detail
class NotificationService { // high-level policy
EmailSender sender = new EmailSender(); // names a concrete detail!
void notify(String m) { sender.sendEmail(m); }
}
class EmailSender { // low-level detail
void sendEmail(String m) { /* SMTP code */ }
}
NotificationService spells out EmailSender. Source-code arrow: NotificationService → EmailSender. To add SMS you must open and edit the policy box.
Now the after — introduce a contract the policy owns and hand the detail in:
// AFTER — arrow points UP from BOTH to the shared contract
interface MessageSender { void send(String m); } // contract (owned by policy)
class EmailSender implements MessageSender { // detail's arrow now points UP
public void send(String m) { /* SMTP code */ }
}
class SmsSender implements MessageSender { // a second detail, same shape
public void send(String m) { /* SMS gateway */ }
}
class NotificationService { // high-level policy
private final MessageSender sender;
NotificationService(MessageSender s) { this.sender = s; } // handed in, never `new`ed
void notify(String m) { sender.send(m); }
}
What changed: NotificationService no longer names EmailSender — it names only MessageSender, a stable shape it owns. The concrete EmailSender now names (implements) the contract, so its arrow flipped upward. That single reversal is the whole principle.
Figure 4 — One box in the middle with pink arrows arriving (counted as Ca) and blue arrows exiting (counted as Ce). The figure turns two abstract letters into something you can literally count on your fingers: tally the incoming heads, tally the outgoing tails.
Because both A and I run from 0 to 1, we can plot every module as a point on a square. This single picture tells you at a glance whether a module is healthy or in trouble.
Figure 5 — The Abstractness (A, up) vs Instability (I, across) square. The diagonal is the main sequenceA+I=1 (healthy). The bottom-left corner is the Zone of Pain; the top-right is the Zone of Uselessness. The figure gives learners a map they can drop any measured module onto — text can name the zones, but only the picture shows how far a point sits from the healthy line.
Recall Can you answer each before reading the main note?
What is a "module" in one phrase? ::: A self-contained named chunk of code — usually one class or file — that does a job.
High-level vs low-level module? ::: High-level = policy / the what; low-level = mechanism / the how (DB, email, I/O).
What does the dependency arrow A→B actually mean? ::: A cannot be written/compiled without naming B — A depends on B.
Why does the arrow's direction matter so much? ::: Change flows backwards up the arrow; you want it pointing toward the thing that changes least (stability).
What is an interface/abstraction? ::: A contract: method names and shapes with no implementation — the "what", never the "how".
In the before/after code, what one change inverts the arrow? ::: The concrete detail starts to implement a contract owned by policy, so its arrow flips upward, and the policy names only the contract.
Where should the interface live for a true inversion? ::: Near/owned by the high-level policy, so the low-level detail's arrow points up to it.
What is Ca (afferent coupling)? ::: The number of outside modules that depend on this one (arrows arriving).
What is Ce (efferent coupling)? ::: The number of modules this one depends on (arrows exiting).
Formula and range of instability I? ::: I=Ce/(Ca+Ce), ranging [0,1]; 0 = maximally stable, 1 = maximally unstable.
What happens to I when Ca+Ce=0? ::: It's 0/0, undefined — an orphan module with no arrows; the metric doesn't apply, so exclude it (report N/A).
What does I=0 tell you? ::: Ce=0: the module depends on nothing, so nothing forces it to change — maximally stable.
Formula for abstractness A? ::: A=Nabstract/Ntotal, the fraction of a module's types that are abstract/interfaces.
What is the "main sequence" ideal? ::: A+I=1: the more depended-upon (stable) a module is, the more abstract it should be.
What is the Zone of Pain? ::: Low A, low I — a concrete module everything depends on: rigid and load-bearing, painful to change.
What is the Zone of Uselessness? ::: High A, high I — an abstract module nobody uses: dead abstraction / clutter.