2.2.1 · D5Design Principles
Question bank — DRY — Don't Repeat Yourself
The core idea we keep poking at: DRY says every piece of knowledge must have one authoritative home. "Knowledge" = a logic rule, a value, a fact. NOT the characters on screen.
True or false — justify
True or false: If two lines of code are character-for-character identical, they violate DRY.
False. DRY is about duplicated knowledge, not duplicated text; two identical lines that encode unrelated decisions (that change for different reasons) are coincidental duplication and should stay separate.
True or false: DRY code is always shorter than WET code.
False. DRY targets a single source of truth, not brevity; you can write longer, clearer code that is still perfectly DRY, or shorter code that still duplicates a fact.
True or false: Merging MAX_USERS = 100 and RETRY_LIMIT = 100 into one constant is a good DRY refactor because both are 100.
False. They share a value by accident, not a reason to change; coupling them means the day one must become 200, you're forced to break the other — this is the wrong abstraction.
True or false: The Rule of Three tells you to DRY code the moment you see it copied a second time.
False. It says tolerate duplication until the third occurrence, so the real, stable pattern is visible before you commit to an abstraction.
True or false: A hard-coded list of countries in the frontend and the same list in the backend validator is a DRY violation.
True. The fact "which countries exist" is one piece of knowledge living in two authoritative places; they can drift, so it belongs in a single source of truth both layers read.
True or false: DRY and the Single Responsibility Principle are unrelated ideas.
False. The SRP test — "does it have one reason to change?" — is exactly the test for whether duplication is real knowledge duplication, so they reinforce each other. See Single Responsibility Principle.
True or false: Sandi Metz argues you should always eliminate duplication as early as possible.
False. Her point is the opposite: "duplication is far cheaper than the wrong abstraction," so premature deduplication can cost more than leaving the copies alone.
True or false: If you DRY a value into one constant, the probability that all copies stay consistent becomes exactly 1.
False. With one home there are no other copies to forget, so consistency risk from missed edits vanishes, but a single edit can still be wrong (, not ).
Spot the error
What's wrong with this reasoning: "This getter and this setter both have 3 lines, so I'll merge them to be DRY."
A getter and a setter do different jobs that change for different reasons; equal line-count is not shared knowledge, so merging couples unrelated logic — that's accidental duplication.
What's wrong: "I made one mega-function with 6 boolean flags so no logic is ever repeated."
Flags and branches to cover every case create a god-abstraction that is harder to read than the duplication was; you've traded a small, honest repeat for Premature Abstraction. See The Wrong Abstraction.
What's wrong: "We copied the tax formula into 4 services, but we documented each one, so it's fine."
Documentation doesn't make edits atomic; changing the tax still means 4 correct edits, and the failure probability stays — the knowledge still has four homes.
What's wrong: "DRY failed us — we extracted a shared function and now every change to it breaks unrelated features."
DRY didn't fail; you DRY'd coincidental duplication, forcing unrelated features through one function. The fix is to un-merge (inline the copies back), not abandon DRY.
Spot the error: A developer avoids the Rule of Three by extracting an abstraction on the very first line of code they write.
With only one occurrence there is no pattern to see yet; abstracting now is guessing at the future — the opposite of what YAGNI advises.
Spot the error: "We stored the config value in a constant AND in the database default AND in an env var so it's very safe."
Three homes for one fact is triple the drift risk, not safety; a single source of truth means every layer reads from one place, not that you copy it defensively.
Why questions
Why is DRY about knowledge rather than about text?
Because the cost of change comes from having to update a decision in many places; identical text encoding different decisions doesn't share that cost, so merging it creates coupling instead of removing duplication.
Why does the number of copies appear both linearly and exponentially in the DRY argument?
Edit cost grows linearly (: each copy is one more edit) while the chance all stay consistent decays exponentially (: each copy is one more independent chance to slip).
Why can "duplication is far cheaper than the wrong abstraction" be true, given DRY hates duplication?
Duplication is a local, visible cost that's easy to fix later; a wrong abstraction spreads through every caller and is expensive to unwind, so tolerating a temporary repeat is the safer bet until the pattern is proven.
Why does the "same reason to change?" test settle most DRY debates?
If two things always change together for one reason, they're one piece of knowledge and belong in one home; if not, they're separate decisions that must stay free to change independently.
Why does a Single Source of Truth matter more for data than clever code deduplication?
Data (state lists, config, prices) is read by many layers that can silently drift; one authoritative source means a fact is defined once and everyone references it, so validation and display can never disagree. See Single Source of Truth.
Why is Refactoring — Extract Method the practical tool most associated with DRY?
It's the concrete move that gives repeated logic a single named home you reference everywhere, turning copies into safely and reversibly.
Edge cases
Edge case: You see duplication exactly twice. DRY it now or wait?
Wait. Two points don't reveal which parts are stable pattern versus coincidence; the Rule of Three says let the third case confirm the shape before extracting.
Edge case: A rule appears in exactly one place today. Is DRY satisfied?
Yes — is the ideal; DRY is already achieved, and forcing an abstraction "just in case" would be premature and violate KISS Principle.
Edge case: Two functions are identical now, but you know one will diverge next sprint for a different reason.
Keep them separate. They already have different reasons to change, so merging would just force an immediate un-merge — treat foreseeable divergence as different knowledge.
Edge case: The duplicated "knowledge" is a single magic number like 0.18 used in two truly-related tax calculations.
DRY it into one named constant; they share the same fact for the same reason, so one authoritative home (
TAX_RATE = 0.18) is correct.Edge case: After DRYing, one caller now needs a slightly different behaviour and you're tempted to add a flag.
That's the signal the abstraction may be wrong; prefer inlining the divergent copy back out over piling on flags — cheaper duplication beats a warping abstraction.
Edge case: You have zero occurrences yet — writing brand-new code. Should DRY guide you?
Not into abstractions; you can't DRY knowledge that doesn't exist twice. Write the simplest thing (YAGNI, KISS Principle) and let real repetition, not imagined repetition, drive extraction later.
Connections
- DRY — Don't Repeat Yourself — the parent this bank drills.
- Rule of Three, WET — Write Everything Twice — timing and the anti-pattern.
- Premature Abstraction / The Wrong Abstraction — the over-DRY failure modes.
- Single Source of Truth — DRY for data.
- Single Responsibility Principle, KISS Principle, YAGNI — the balancing forces.
- Refactoring — Extract Method — the safe extraction tool.