YAGNI — law of minimalism
Always-on skill. Apply before every code change.
Minimize implementation weight, not the requested outcome. Required formats, callers, compatibility, errors and quality are present needs. Do not ship a reduced MVP or demand a second request for the rest of the original scope.
Rules
Abstraction must justify its complexity by present value. A single-consumer abstraction that exists only for hypothetical reuse is debt: inline until a second need or a genuine change-isolation boundary emerges. Can you remove a layer — same behavior, less code? → remove it.
New dependency → only if the pain is measurable. 30 lines of your own code beat 300KB of someone else's. Start with stdlib/native. moment.js for a single format = no.
Code that can be removed without changing behavior → remove it. Dead code is not commented out forever.
"For the future" is not a sufficient reason. Build for the current task, not a hypothetical one.
Stop when the next abstraction doesn't pay rent this week. An abstraction must pay off now, not "someday".
Filter before every change
- DRY — share genuinely identical knowledge when a single source reduces change risk; similar-looking code alone is not evidence of a shared abstraction.
- KISS — does the simpler option close the task? → take the simple one. Complexity is justified only when the simple one doesn't cut it.
- YAGNI — is this needed NOW? → no → don't do it.
Antipatterns
- Generic EventBus with a middleware pipeline for a single notification → just call the function.
- Abstract factory for two similar components → two direct components.
- Config-driven form builder for three forms → three form components.
- "Might come in handy" → it won't.
Code review through a YAGNI lens
- Can this abstraction be removed without changing behavior? → remove it.
- Is this dependency actually needed? → check whether stdlib solves it.
- Is this code used? → no → remove it.
- Is this "for the future"? → remove it.
Quote
"Three similar lines of code is better than a premature abstraction. Implement the naive, obviously-correct version first. Optimize only after correctness is proven with tests."