The Problem It Solves
A validation rule exists in three places (API handler, service, batch job). A regulation changes; a developer fixes the handler and service, misses the batch job. For months the system silently applies two different rules depending on entry path — discovered by an audit, not by tests. That is duplication’s signature cost: copies drift. Each copy compiles, passes its local tests, and diverges quietly.
DRY (Don’t Repeat Yourself — Hunt & Thomas) targets knowledge duplication: every rule, calculation, or policy should have exactly one authoritative home.
t0: three identical copies t1: one copy edited
┌─────────┐ ┌─────────┐
│ Handler │ tax = base * 0.18 │ Handler │ tax = base * 0.12 ← new law
└─────────┘ └─────────┘
┌─────────┐ ┌─────────┐
│ Service │ tax = base * 0.18 │ Service │ tax = base * 0.12
└─────────┘ └─────────┘
┌─────────┐ ┌─────────┐
│ Batch │ tax = base * 0.18 │ Batch │ tax = base * 0.18 ← MISSED
└─────────┘ └─────────┘ silent inconsistency
Mechanics — Extracting Knowledge
// knowledge scattered:
long gst(Item i) { return i.base() * 18 / 100; } // in OrderService
long computeTax(Item i) { return (long)(i.base() * 0.18); } // in InvoiceService
// single authoritative home:
final class TaxPolicy {
private static final int GST_PERCENT = 18;
static long gst(long basePaise) { return basePaise * GST_PERCENT / 100; }
}
The extraction matters more for where future readers will look than for line count: one named concept (TaxPolicy) becomes searchable, testable, and changeable once.
Scope of “Duplication”
- Logic: same calculation, same branch structure in multiple methods.
- Data/config: magic numbers, thresholds, feature names repeated across files.
- Documentation-as-duplication: comments restating what code does rot faster than code.
- Structural: near-identical classes differing in one field → parameterize.
The Counter-Trap: Wrong Abstraction
Merging code that merely looks similar but varies for different reasons creates a parameterized monster where every change means untangling accidental unification (“duplication is far cheaper than the wrong abstraction” — Sandi Metz).
| Signal | Action |
|---|---|
| Two copies, same reason to exist | Extract now |
| Rule of three: third copy appears | Extract |
| Copies differ in unrelated dimensions | Keep separate |
| Merged function needs boolean flags per caller | Un-merge — abstraction was wrong |
Interview Signals
- Citing rule of three rather than reflexive DRY signals judgment.
- The senior answer acknowledges the failure mode: “I’d extract when copies share a reason to change — not merely similar text.”
Premium Content
Unlock DRY and all premium lessons with a subscription.
From ₹199.99/year — See plans