DRY - Don't Repeat Yourself
Every piece of knowledge should have one authoritative place to live in a system.
Not one copy of the code - one copy of the fact. A free-shipping threshold hardcoded as
50 in the checkout summary and again in the invoice PDF generator is not two pieces of
logic; it is one fact that forgot to pick a home.
Why it exists
The day that fact changes, the cost of having two homes for it comes due. Marketing decides
free shipping now kicks in at $75. Someone updates the checkout summary, ships it, and moves
on. Three weeks later a support ticket comes in: a customer paid shipping on a $60 order that
the invoice PDF - still running on the old 50 - insists should have been free. Nobody lied
to the customer on purpose. The fact just had two addresses, and only one got the memo.
Multiply that by twelve places instead of two and you no longer have a bug, you have an archaeology project: finding every buried copy of a fact before you can trust that changing it changed anything.
A duplicated fact, and its fix
Try it yourself: before revealing the fix above, write down what you would extract if a third call site - a marketing banner that says "Free shipping over $50!" - also needed to know the threshold. Does your answer still work if the threshold someday needs to vary by country?
The cost of overusing it
DRY has a well-known failure mode: applying it to code that merely looks alike instead of
code that means the same thing. Two five-line validation functions - one checking a zip
code, one checking a product SKU - can be byte-for-byte identical today and still be
coincidentally identical, not duplicated. Merge them into one validateFormat() and the day
the SKU rule needs a checksum digit, you are untangling a shared function that never should
have been shared, adding a type parameter and a branch to serve two callers that had
nothing to do with each other.
Repetition is cheap to fix later. The wrong abstraction, once three call sites depend on it, is not. When in doubt about whether two blocks share a fact or just share a shape, wait for a third occurrence before extracting - two is a coincidence you can still afford.
How it relates to its neighbours
DRY and Encapsulate What Varies sound similar and are not the same axis. DRY is about sameness: one fact, one home, regardless of whether that fact ever changes. Encapsulate What Varies is about change: walling off a part of a class specifically because it changes on a different schedule than the rest, even if that part appears exactly once. A constant that never varies can still violate DRY if it is copy-pasted; a piece of code that appears exactly once can still need encapsulating if it is volatile.
Where you'll see it in the pattern catalog
Template Method exists largely to eliminate DRY violations in algorithm skeletons - two subclasses that each reimplement "open, read, process, close" with only the process step actually differing. Strategy solves the same duplication from the composition side. Anywhere you see near-identical method bodies in sibling classes, one of these two patterns is usually the DRY fix waiting to happen.
Check yourself
A free-shipping threshold of $50 is hardcoded in both the checkout summary and the invoice generator. What did DRY actually get violated by?