Don't Repeat Yourself: the second copy is the bug
I watched a team spend a fortnight arguing about a helper function. Six callers, four boolean flags, a name that had been accurate for the first caller and never since. Everyone agreed it was fine because the alternative was duplication. Duplication is what the book warns you about.
Hunt and Thomas wrote two sentences in 1999, and only the first one gets quoted. Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. That is the rule. The second sentence is hard: it tells you what to do when two lines look alike.
The word is knowledge. Two lines that look the same are not automatically the same fact. Two lines that encode the same fact are.
The reflex
Extraction on sight is the failure mode. You see two similar blocks and pull them into a function. You feel like you have done the tidy thing.
You commit to those two call sites changing together forever. If the resemblance was coincidence, that commitment is a liability. It shows up as a flag parameter the first time one caller needs something slightly different. Then a second flag. By the time anyone reads the signature, the name covers nothing.
What counts as knowledge
A tax rate is knowledge. A date format is knowledge. A validation rule about what makes an order valid is knowledge. Two loops that happen to iterate the same way today are not.
The test I use: if the business changed this fact, would both copies need to change? If yes, they are one fact with two homes and the second copy is the bug. If no, they are two facts that currently look alike, and merging them is the mistake.
The bounded context line
Inside a bounded context, deduplicate freely. It is cheap insurance and the call sites genuinely move together.
Across a context boundary, do not. The same word means different things on either side. A shared helper makes you negotiate every time one side's meaning shifts. Two copies of something that looks identical but means two different things is not duplication. It is two models that happen to share a spelling.
Why agents make this sharper
A developer who meets the flagged helper works out what each branch is for and moves on. An agent reads the name and the signature and takes both as given. One over-eager extraction becomes the vocabulary for everything generated around it.
I have seen https://prickles.org/tenet/dont-repeat-yourself/F3
