design·lab

Core principle

YAGNI — You Aren't Gonna Need It

Build what the current requirement needs — nothing more. Imagined future needs cost you now and rarely pay off later.

✗ The problem

Speculative generality: designing for futures that never arrive

The task is "save a note". The code ships a plugin system, five export formats, a 12-flag config object, and an abstract strategy — for one localStorage call.

class StorageStrategy { save(k, v) { throw 'abstract'; } }
class LocalStorageStrategy extends StorageStrategy { /* only impl */ }

function saveNote(text, {
  strategy = new LocalStorageStrategy(),
  exportFormat = 'json',   // txt/md/pdf/xml unused
  plugins = [],           // none exist yet
  // ...9 more flags nobody sets
} = {}) {
  strategy.save('note', text);
}
You pay to build, test, and maintain code for futures that never arrive — every unused branch is a bug waiting to happen.
✓ Build only what's needed now

Ship the one line the requirement actually asks for

No strategy, no config, no plugins — just the behavior today's requirement needs.

Before — bloated, hypothetical

function saveNote(text, {
  strategy = new LocalStorageStrategy(),
  exportFormat = 'json',
  plugins = [],
  /* 9 more flags */
} = {}) { strategy.save('note', text); }

After — exactly what's needed

function saveNote(text) {
  localStorage.setItem('note', text);
}
Need a second storage backend for real one day? Add the abstraction then — see Open/Closed.
✓ See it live

Toggle speculative features — watch cost climb, value stay flat

These are "needed now". Toggle the "maybe someday" ones ON and watch complexity, maintenance cost, and surfaced bugs rise — while shipped value never moves.

Save note to storageneeded now
Show saved confirmationneeded now
🔌 Plugin systemmaybe someday
📤 5 export formatsmaybe someday
⚙️ 12-flag config objectmaybe someday
🧩 Abstract StorageStrategymaybe someday
Complexity / LOC18 lines
Maintenance cost0%
Bugs surfaced0

Shipped value delivered to the user: 2 / 2 core features — constant, no matter how many speculative toggles are ON.

✓ Takeaway

Build for the requirement you have, not the one you imagine

  • Don't build for imagined futures — implement the current requirement, refactor when the need becomes real.
  • Speculative code is cost + risk (build, test, maintain, debug) with no payoff until — if ever — it's used.
  • Pairs with Open/Closed: add the abstraction when the second real case shows up, not before.
  • Caution: YAGNI isn't an excuse to skip real design or ignore known, certain near-term requirements.