Rule 32 of 38 · Chapter V — Complexity Has a Cost
Two is a coincidence, three is a pattern
Why this rule exists
Duplication is cheaper to fix than the wrong abstraction is to unwind. The first repetition might be coincidence; two things that merely look alike today can easily diverge tomorrow. Waiting for the third occurrence gives you enough evidence to see the real pattern, so the abstraction you build matches how the code actually varies rather than how you guessed it would.
In practice
When you notice a second copy, resist the urge to unify immediately; note it and move on. On the third, study all three uses together and factor out only what they genuinely share, leaving the differences as parameters. If forcing them into one shape requires flags and special cases, that's a sign they aren't the same thing after all. Let the abstraction follow the evidence.
Example
// unify after 2, forced to diverge
function fmt(x, kind) {
if (kind === 'usd') return '$' + x;
if (kind === 'eur') return x + ' EUR';
if (kind === 'pct') return x + '%';
}// wait for the third; keep them apart
const usd = x => '$' + x;
const eur = x => x + ' EUR';
const pct = x => x + '%';When it doesn't apply
Some duplication is worth removing on sight: a critical constant, a security check, or a business rule that must stay identical everywhere. And obvious, exact copies with no plausible reason to diverge can be merged the moment you see them.