YAGNI: Skip Presumptive Features to Minimize Costs
Don't build features needed 6 months out now—incur build costs, 2 months revenue delay, ongoing carry costs, and 2/3 chance they're useless or wrong anyway.
Four Costs of Building Presumptive Features
Presumptive features—code for capabilities not yet needed—impose four key costs, even if they prove useful. First, build cost wastes effort on analysis, coding, and testing something unnecessary, like adding piracy risk pricing to a storm risk pricer 6 months early. Second, delay cost diverts effort from urgent features; skipping piracy lets you ship storm sales software 2 months sooner, capturing revenue immediately. Third, carry cost adds complexity that slows all future work—piracy code might delay storm sales by 2 weeks via harder debugging and changes, compounding across features until needed (or forever if removed). Fourth, repair cost hits when teams learn better implementations later, accruing technical debt from outdated designs.
To counter 'cheaper now' arguments, compare total costs including ⅔ failure odds (from Microsoft analysis: only ⅓ of carefully planned features improved metrics). Mentally simulate later refactoring often reveals it's not much harder—or spot low-cost prep like using lookup tables over literals for future i18n.
High Odds Presumptive Features Fail or Change
Agile embraces changing requirements, so upfront predictions falter—e.g., a navy wiping out pirates kills the need entirely. Even accurate foresight yields wrong implementations as teams learn user needs, tools, and code interactions. Abstractions for future risks (e.g., parameterizing storm pricer for piracy) presume correct designs, but reality mismatches raise complexity without benefit. YAGNI presumes such extensibility guilty if it obscures current code.
Spectrum of failure: fully useless (build cost only), partially useful (carry until activation), or 'right feature, wrong build' (repair debt). Small-scale YAGNI matters too—e.g., delay regex group highlighting until needed; skip unused fields/methods. These micro-decisions cumulatively slash codebase complexity and accelerate urgent delivery.
YAGNI Demands—and Reinforces—Malleable Code
YAGNI forbids only complexity for unused future capabilities; zero-complexity prep (rare) is fine. Crucially, it excludes investments in changeability: refactoring, self-testing code, and continuous delivery aren't presumptive—they enable YAGNI by keeping code malleable. Without them, delaying features becomes painful, turning YAGNI into a curse.
Failures occur when early cheap changes avert later expensive ones, but these are rare, availability-biased memories; successes (avoided waste) dominate. YAGNI thus both requires and bolsters evolutionary design: build simple now, adapt precisely later.