extract on the third repeat, not the first
DRY -- Don't Repeat Yourself
DRY says every piece of knowledge has one authoritative home. The rule of three tempers it: don't abstract until the third occurrence, or you'll build the wrong abstraction and couple things that should move apart.
Two copies is a coincidence; three is a pattern that has earned a name.
In the wild
The Rule of Three
When to extract: the first copy is fine, the second is a coincidence, the third confirms a pattern.
# 1st time: just write it.
price_a = qty_a * unit_a * (1 - discount_a)
# 2nd time: a coincidence -- resist abstracting yet.
price_b = qty_b * unit_b * (1 - discount_b)
# 3rd time: NOW extract -- the pattern is proven.
def line_total(qty, unit, discount):
return qty * unit * (1 - discount)early: an abstraction that fights the 3rd case three: extract once the pattern is proven
Knowledge, Not Code
Two snippets that look identical can encode different decisions. DRY-ing them couples the unrelated.
// These LOOK identical, but encode two different policies:
const taxRate = (amt) => amt * 0.0825; // sales tax (law)
const tipRate = (amt) => amt * 0.0825; // suggested tip (today)
// WRONG-DRY: merge them and they change together by accident
const rate = (amt) => amt * 0.0825; // now tip can never differ from tax
// RIGHT: same value, different KNOWLEDGE -- keep them apart
const SALES_TAX = 0.0825, DEFAULT_TIP = 0.0825;merged: changing tip silently changes tax separate: each rate evolves on its own
Single Source of Truth
Knowledge with one home cannot disagree with itself; copies eventually do.
// SMELL: the same rule compiled in three files, subtly drifted
var reA = regexp.MustCompile(`^\d{3}-\d{4}$`)
var reB = regexp.MustCompile(`^\d{3}-\d{3}$`) // typo, drifted
// RIGHT: one exported pattern, defined once
var PhoneRE = regexp.MustCompile(`^\d{3}-\d{4}$`)copies: two patterns, one concept shared: PhoneRE, defined once
Mapped weaknesses (CWE)
On its own, this defect is catalogued by MITRE as one or more of these weaknesses. The exploitable vulnerability usually appears only when it chains or combines with another.