Module 02 · SOLID and friends · Lesson 6 of 7
DRY, KISS and YAGNI
Three short principles that keep the others honest. DRY is about one source of truth for knowledge, not removing similar-looking code; KISS prefers the simplest design that works; YAGNI says not to build for requirements you do not have.
Why it matters
SOLID can be over-applied: every class split, every variation abstracted, every dependency inverted, until a simple feature lives in fifteen files. These three principles are the counterweight. Misread, they cause their own damage: "DRY" used to merge code that only looks alike, producing an abstraction full of flags. Read correctly, they keep designs small, honest and easy to change.
The idea
| Principle | Says | Common misreading |
|---|---|---|
| DRY: don't repeat yourself | Every piece of knowledge should have one authoritative representation | Any two similar-looking blocks of code must be merged |
| KISS: keep it simple | Prefer the simplest design that meets the actual requirements | Write the least code possible, however cryptic |
| YAGNI: you aren't gonna need it | Do not build features or flexibility for requirements you do not have yet | Never design for change at all |
DRY is about knowledge, not text
The tax rate, the rule for when an order can ship, the format of an account number: each is knowledge, and if it lives in three places, changing it means finding all three and getting them identical. That is the duplication DRY targets. Two functions that happen to look similar but encode different rules (shipping rules for domestic and international orders, which change for different reasons) are not duplication; merging them couples two things that should evolve independently.
A widely repeated observation in software design is that duplication is far cheaper than the wrong abstraction. When an abstraction starts sprouting boolean parameters and special cases for each caller, the fix is often to inline it back into its callers and let each evolve on its own.
The rule of three
A practical way to apply DRY without guessing: tolerate the first duplication, notice the second, extract on the third, when you can see what the cases genuinely share and what differs. Abstractions extracted from three real examples are far more likely to fit the fourth than one extracted from a single example and a prediction.
KISS
Simple means easy to understand and change, not merely short. A plain loop beats a clever stream pipeline nobody can debug; three explicit classes beat a generic framework built to handle cases that do not exist. In interviews and in code, start with the most direct design that handles the stated requirements, then add structure where a requirement or a demonstrated change calls for it.
YAGNI
Every speculative feature or extension point costs time to build, code to read, tests to maintain and constraints on future design, and most speculations turn out wrong. Build for today's requirements, keep the code clean enough that tomorrow's requirement is easy to add, and add it when it arrives. YAGNI is not an argument against good structure; it is an argument against structure for problems you do not have.
Reconciling them with SOLID
SOLID tells you how to make change cheap; DRY, KISS and YAGNI tell you when it is worth it. Introduce the open-closed extension point when variation is real or clearly coming, segregate interfaces when clients actually differ, invert the dependencies that are actually volatile. Without that restraint, principles become ceremony.
Trade-offs
Duplication of knowledge risks inconsistency; premature abstraction risks rigid, flag-ridden code. Simplicity risks rework when requirements grow; speculative flexibility risks complexity that never pays off. The balance shifts with context: a public library must anticipate more change than an internal service, and a prototype less than either.
In an interview
Show restraint explicitly, which interviewers value: "I am keeping parking-spot allocation as a simple nearest-free-spot method for now. If we need different allocation rules per lot, that becomes a strategy, but nothing in the requirements asks for it yet." It demonstrates you know the tools and when not to use them.
Check yourself
A shared calculateFee(order, isInternational, isExpress, isMember, hasCustoms) function serves six callers, and every new rule for one caller breaks another. What does a correct reading of DRY suggest?