Suggest an editImprove this articleRefine the answer for “YAGNI (you aren't gonna need it)”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**YAGNI (You Aren't Gonna Need It)** - only build what the current spec requires. Skip anything else until a real need arrives. ```javascript // spec says "filter active users" - nothing more function getActiveUsers(users) { return users.filter(u => u.active); } ``` **Key point:** write code for today's requirements, not tomorrow's guesses.Shown above the full answer for quick recall.Answer (EN)Image**YAGNI (You Aren't Gonna Need It)** - a development principle that says only implement what the current spec requires, and add more only when a real need arrives. ## Theory ### TL;DR - Analogy: build the kitchen now, not the chef's pantry you might want someday. - Core rule: "Does the spec demand it today?" If no, skip it. - Main cost: teams waste 20-30% of dev time on features nobody ever uses. - YAGNI vs DRY: DRY removes current duplication; YAGNI blocks speculative future code. - Break it for security basics and proven structural patterns like MVC skeleton. ### Quick example ```javascript // Task: filter users by active status. Nothing else in the spec. // YAGNI violation - sorting and pagination added "for later" function getActiveUsersBad(users, page = 1, sortBy = 'name') { return users .filter(u => u.active) // needed .sort((a, b) => a[sortBy].localeCompare(b[sortBy])) // not needed yet .slice((page - 1) * 10, page * 10); // not needed yet } // YAGNI: do exactly what the spec says function getActiveUsers(users) { return users.filter(u => u.active); } // Output: [{ name: 'Alice', active: true }, { name: 'Bob', active: true }] ``` The bad version isn't just verbose. It adds code nobody will test, maintain, or probably ever call. ### Why it matters Speculative features cost twice: once to write, once to maintain when real requirements change. That second hit is the painful one, because you're refactoring code that never served a single user. I've seen a user roles table built before launch and deleted two weeks later, zero users ever touched it, two days gone. The 20-30% waste estimate from teams that ignore YAGNI is conservative. Anyone who has cleaned up a codebase full of "just in case" abstractions knows how bad it gets. One clarification worth making: YAGNI doesn't mean never plan ahead. It means don't write the code until the need is proven. ### When to use - Spec lacks the feature: skip it. Write it when the ticket arrives. - User story says "maybe later": implement the minimum that works now. - Prototype phase: smallest thing that tests the hypothesis. - Refactor pass: add a feature only if metrics show a real bottleneck. ### Common mistakes **Adding config params "just in case"** ```javascript // Wrong - three params nobody asked for function filterUsers(users, active = true, minAge = 0, country = '') { return users.filter( u => u.active && u.age >= minAge && (country ? u.country === country : true) ); } // Right - spec said "active users only" function filterUsers(users) { return users.filter(u => u.active); } ``` Adding params now means writing tests for them, keeping them in docs, and explaining them to every new dev. Add them when a ticket demands it. **Over-abstracting for hypothetical plugins** ```javascript // Wrong - base class for plugins that don't exist yet class UserFilter { process(users) {} // empty method waiting for "someday" } // Right - just a function function filterUsers(users) { return users.filter(u => u.active); } ``` A common story: a dev builds a plugin system on day one, it's never extended, and six months later every real feature has to work around the unused abstraction. **Prebuilding infrastructure for unproven scale** Adding a Redis queue for a service handling 10 users per day creates immediate ops overhead with zero guaranteed payoff. The sequence is: in-memory array first, then a database, then a queue - only after load tests show you actually need it. **Speculating on UI states** Unused tabs, disabled buttons with no spec, loading states for features not yet built. All of it becomes dead code that junior devs debug without any context. ### Real-world usage - React: `create-react-app` ships with minimal defaults. No TypeScript, no Redux, no routing until you add them. - Express: start with a base router. Add rate limiting after a real security review, not before. - Redux: add actions only for live features. No "future offline mode" sagas upfront. - Node CLI tools: `fs.readFileSync` works fine until profiling shows a bottleneck. Then switch. ### Follow-up questions **Q:** What is YAGNI? **A:** A principle that says build only what the current spec requires. If the need isn't proven, the code doesn't exist yet. **Q:** How does YAGNI differ from DRY? **A:** DRY removes duplication in code that already exists. YAGNI stops you from writing code that doesn't need to exist at all. **Q:** When is it okay to break YAGNI? **A:** For proven patterns like MVC structure or input sanitization. Security basics always apply, even before users ask for them. **Q:** How do you measure whether a feature is actually needed? **A:** Track user tickets and usage metrics. If fewer than 5% of users request something over three months, it probably doesn't belong in the next sprint. Senior devs tie this to OKRs. **Q:** Can YAGNI conflict with agile planning? **A:** Not if you treat each sprint as an MVP cycle. Use spike stories for genuine unknowns. Everything else ships only when a user story proves the need. ## Examples ### Basic: YAGNI in an Express endpoint ```javascript // Spec: return active users with a valid email. Nothing else. app.get('/api/users', (req, res) => { const activeUsers = users.filter(u => u.active && u.email); res.json(activeUsers); }); // GET /api/users → [{ id: 1, name: 'Alice', active: true, email: 'a@test.com' }] // No auth, no pagination - spec doesn't ask for it yet. ``` This endpoint does exactly what the current spec says. Auth gets added when the security ticket arrives, not before. ### Intermediate: sort on demand, not upfront ```javascript // Users requested sorting after launch. No need to prebuild it. function UserList({ users }) { const [sortBy, setSortBy] = useState(null); // null until the user clicks const sorted = sortBy ? [...users].sort((a, b) => a[sortBy].localeCompare(b[sortBy])) : users; // no sort logic runs until needed return ( <div> {sorted.map(u => <div key={u.id}>{u.name}</div>)} <button onClick={() => setSortBy('name')}>Sort by name</button> </div> ); } ``` The sort exists because users actually asked for it after launch. Before that, the component shipped without it. Adding it later took one afternoon, not a week of refactoring a pre-built sort system.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.