YAGNI
debt(d9/e5/b7/t5)
Closest to 'silent in production until users hit it' (d9). The detection_hints explicitly state 'automated: no' and the code_pattern examples (plugin system for one plugin, generic framework for one use case) describe structural over-engineering that is invisible to any tool — it only becomes apparent through accumulated maintenance cost and wasted developer time. No linter or SAST tool flags speculative abstractions.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says 'delete the feature/abstraction/flexibility' but common_mistakes include plugin systems, factory hierarchies, configuration layers, and multiple output formats — these over-engineered structures are entangled across multiple files and call sites. While deletion is conceptually simple, the speculative abstractions that YAGNI violations produce typically require untangling from dependent code across a component, making it more than a one-line patch but usually not a full cross-cutting architectural rework.
Closest to 'strong gravitational pull' (b7). YAGNI violations apply across web, cli, and queue-worker contexts per applies_to. Speculative abstractions like plugin systems, factory hierarchies, and configuration layers become load-bearing structures — every future change must navigate around or through them. The tags (principles, agile, xp) indicate this is a codebase-shaping concern: an unnecessary abstraction layer shapes how all future code in that component must be written, creating persistent productivity tax that approaches gravitational pull.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field captures the canonical wrong belief exactly: developers confuse YAGNI with 'write minimum code and never think ahead,' when it actually only discourages unasked-for features — architectural thinking is still valuable. This is a well-documented, commonly learned lesson in agile/XP communities, but competent developers regularly fall into it by conflating responsible design with premature optimisation or by accepting stakeholder pressure to 'just add a flag for that.'
Also Known As
TL;DR
Explanation
YAGNI is an Extreme Programming principle arguing that developers should not add functionality based on speculation about future needs. Premature generalisation creates dead code, complicates maintenance, and often builds the wrong abstraction — requirements change and the speculative feature is never used or is removed. Implement the simplest thing that works for current requirements. Refactor to accommodate new requirements when they actually arrive — by then you'll have more information to design correctly.
Common Misconception
Why It Matters
Common Mistakes
- Designing plugin systems, configuration layers, or factory hierarchies for a single use case.
- Adding method parameters for 'future options' that never materialise.
- Implementing multiple output formats (JSON, XML, CSV) when only JSON is currently needed.
- Confusing YAGNI with not writing tests — tests for current requirements are not speculative.
Avoid When
- Core infrastructure decisions (database schema, API contracts, auth) where retrofitting is expensive — some upfront design is justified.
- Security — do not defer input validation, auth checks, or encryption on the grounds that attacks may not happen.
- Accessibility and internationalisation in consumer products — retrofitting is far more expensive than building in from the start.
When To Use
- Feature development — do not build configurability, plugins, or extension points until a real need exists.
- Abstractions — do not create interfaces or base classes for a single implementation that may never have a second.
- Performance optimisation — do not optimise before profiling shows an actual bottleneck.
- Resisting stakeholder requests to 'just add a flag for that' — every flag is future complexity.
Code Examples
class UserRepository {
// Built 'just in case' — never called
public function findByAstrologicalSign(string $sign): array { ... }
public function exportToExcel(): string { ... }
public function importFromLegacyCsv(): void { ... }
}
class UserRepository {
public function findById(int $id): ?User { ... }
public function findByEmail(string $email): ?User { ... }
public function save(User $user): void { ... }
// Add methods when a real feature requires them
}