skip to content

KISS and YAGNI

Two disciplines for not building what you do not need yet: keep the solution simple, and defer the flexibility nobody has asked for. Interviewers use them to probe whether you can distinguish essential complexity from complexity you invented.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

6

What do the design principles KISS ("Keep It Simple, Stupid") and YAGNI ("You Aren't Gonna Need It") each tell a developer to do, and how do the two differ?

level: juniorimportance: must knowfreq 78%

answer

  1. KISS = form; YAGNI = scope/timing
  2. "Implement when needed, never when foreseen" — Jeffries, XP
  3. Presumptive feature = the target
  4. Simple ≠ short; clever one-liner isn't simple
  5. YAGNI never excuses tests, errors, security

basics

~20 s

KISS: choose the simplest solution that works — fewer moving parts, easier to read. YAGNI: don't build a feature or extra flexibility until something actually needs it. KISS shapes how you build; YAGNI decides whether to build now.

solid answer

~50 s

KISS says: among solutions that satisfy the requirement, prefer the one with the fewest concepts, indirections and moving parts, because someone else must read, debug and change it. YAGNI (from Extreme Programming) says: implement capability when a real, present need exists — never because you foresee needing it later. So KISS governs the *form* of what you decided to build; YAGNI governs the *scope and timing* of what you build at all. YAGNI targets presumptive features and speculative extensibility — the config flag with one value, the plugin system with one plugin, the abstraction layer over a database you will never swap. It does not license skipping tests, error handling, input validation, security, or sane module boundaries: those serve today's code, not a guessed future. Misapplied, KISS becomes "I didn't think about it" and YAGNI becomes "I cut corners".

go deeper

for a junior

State both definitions correctly and give one concrete example of each (a config flag with one value; a clever one-liner rewritten as three clear lines). Say explicitly that YAGNI is not an excuse to skip tests or error handling.

for a middle

Draw the scope-vs-form distinction crisply, list the classic speculative constructs (single-implementation interface, unused options bag, DB abstraction "in case we swap"), and mention that YAGNI's bet is that adding it later is cheap.

for a senior

Frame YAGNI as an economic bet and name where the bet fails: irreversible decisions such as published APIs, wire/storage formats, and security models. Explain how KISS keeps that bet valid by keeping change cheap.

for a principal

Position both as defaults inside a broader decision policy: reversible decisions default to YAGNI and get deferred to the last responsible moment; irreversible ones get explicit up-front design and a written record. Discuss how you enforce this culturally without it degrading into "no design".

## The two principles, precisely **KISS — "Keep It Simple, Stupid"** originated outside software: Kelly Johnson at Lockheed's Skunk Works (1960s) demanded aircraft repairable in the field by an average mechanic with basic tools. Transplanted to software it means: *of the designs that meet the requirement, prefer the one a competent stranger can understand and change fastest.* Simplicity is measured in **concepts a reader must hold in their head** — number of classes/functions involved, layers of indirection, branches, implicit conventions, configuration knobs, runtime moving parts (threads, caches, queues, services). KISS is **not** "fewest lines of code". A dense one-liner packing four operations, or a clever bit-twiddling trick, is *short* but not *simple*. Nor is it "no structure": splitting a 600-line function into five named steps adds lines and reduces complexity, because each piece is independently understandable. **YAGNI — "You Aren't Gonna Need It"** comes from Extreme Programming (Kent Beck, Ron Jeffries, late 1990s). Jeffries' formulation: *"Always implement things when you actually need them, never when you just foresee that you need them."* The target is the **presumptive feature** — functionality or flexibility added because someone predicts a future requirement. ## Why they are different principles - YAGNI is a **scope/timing** decision: *should this capability exist at all right now?* - KISS is a **form** decision: *given that it must exist, what shape should it take?* You can violate one while honouring the other. A speculative plugin framework can be beautifully written (KISS-clean internally) and still be a YAGNI violation, because nothing needs it. Conversely, a genuinely required feature can be implemented as an unreadable tangle — YAGNI satisfied, KISS violated. ## Typical YAGNI violations | Symptom | What it looks like | |---|---| | Config flag with one value | `strategy: "default"` and no other strategy exists | | Plugin/extension point with one implementation | Interface + factory + registry, one concrete class | | Generic "future-proof" abstraction layer | A repository wrapping the database "in case we swap it" (you won't) | | Unused parameters/hooks | `process(data, options)` where `options` is never non-empty | | Premature scaling machinery | Sharding, caching tier, message queue before any load exists | | Multi-tenancy / i18n / audit hooks | Built "because sales might sell it" | ## What YAGNI explicitly does NOT excuse This is the most common interview trap. YAGNI applies to **capability you don't need yet**, not to quality attributes serving code that exists today: - automated tests for the behaviour you just wrote - handling errors and invalid input that can occur today - security controls (authn/authz, escaping, secrets handling) for endpoints that exist - naming, cohesion, module boundaries — these make today's code cheap to change - required non-functional constraints already in the contract (e.g., a stated latency SLA) "We skipped auth because YAGNI" is not YAGNI; it is missing a present requirement. ## How they interact YAGNI is what makes KISS survivable over time. Every speculative extension point permanently raises the baseline complexity everyone must read past — so deferring it *is* how you keep the system simple. Conversely, KISS keeps YAGNI cheap: if today's code is simple and well-tested, adding the feature later when it is real costs little, which is exactly the bet YAGNI makes. ## The counterweight Both principles assume change is cheap. When it is not — a published API other teams depend on, an on-disk/wire data format, a security model, a persistence schema in a system with no migration story — you must design deliberately up front, because retrofitting is expensive or impossible. YAGNI defers **reversible** decisions; it does not tell you to be careless with irreversible ones.

  • Someone justifies skipping input validation and tests by saying "YAGNI". Is that a correct use of the principle?
    No. YAGNI concerns capability nobody needs yet. Validation and tests serve code that exists today and make it cheap to change — they are present requirements, not speculation. Misusing YAGNI this way is how it gets a bad reputation.
  • Is a hand-rolled 300-line function 'simple' by KISS because it has no abstractions?
    No. KISS minimises the concepts a reader must hold at once, not the number of named units. Splitting that function into a few well-named steps usually adds lines while reducing what the reader must understand at any moment.

KISS is packing a suitcase neatly so anything is easy to find. YAGNI is not packing the snorkel for a ski trip because "we might detour to the coast". Different decisions: how you pack versus what goes in.

context

open as a page

Fred Brooks distinguished "essential" from "accidental" complexity in software. What is the difference, and how does that distinction guide you when someone asks you to "simplify" a codebase?

level: middleimportance: must knowfreq 52%

basics

~20 s

Essential complexity comes from the problem itself — real rules, cases and constraints you cannot delete. Accidental complexity comes from how we built it: tooling, layers, workarounds, duplication. Simplifying means removing accidental complexity; essential complexity can only be moved or made explicit.

open as a page

Martin Fowler frames YAGNI ("You Aren't Gonna Need It") as an economic trade-off between building a presumptive feature now and carrying it. Walk through those costs, and name the situations where applying YAGNI is the wrong call.

level: seniorimportance: must knowfreq 42%

basics

~20 s

Building early costs the build itself plus a delay to real work, and if you guessed wrong you carry and repair dead complexity forever. YAGNI fails where changing later is expensive or impossible: published APIs, stored/wire data formats, security models, and hard non-functional requirements.

open as a page

What is the "speculative generality" code smell, and how do the Rule of Three and Sandi Metz's maxim "duplication is far cheaper than the wrong abstraction" help you decide when to introduce an abstraction?

level: middleimportance: should knowfreq 45%

basics

~20 s

Speculative generality is machinery built for a future that never arrives — an interface with one implementation, unused parameters, hooks nobody calls. Rule of Three: wait for the third occurrence before abstracting. Until then, duplication is safer than guessing the wrong shared shape.

open as a page

How do you build a system that stays cheap to change without violating YAGNI by building speculative extension points? Discuss the mechanisms you would actually use.

level: principalimportance: should knowfreq 30%

basics

~20 s

Buy options, not features: keep code well-factored and tested, defer decisions to the last responsible moment, make data and contracts evolvable (versioned, additive-only, expand/contract migrations), and spend up-front design only on decisions that are hard to reverse.

open as a page

Rich Hickey's talk "Simple Made Easy" argues that "simple" and "easy" are different properties. What is the distinction, and how would you argue objectively that one design is simpler than another rather than just more familiar?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

Simple means one concern, not braided together with others — an objective property of the design. Easy means familiar or close at hand — relative to you. To argue simplicity, count interleaved concerns, dependencies, states and hidden couplings, not how quickly you can start.

open as a page