Skip to content
FollowtheDamnCode

DRY, KISS, and YAGNI

Three rules of thumb that keep the principles honest — one source of truth, the simplest thing that works, and nothing you don't need yet.

Big idea

  • DRY — Don't Repeat Yourself: every piece of knowledge should have one authoritative home.
  • KISS — Keep It Simple: prefer the simplest design that solves today's problem clearly.
  • YAGNI — You Aren't Gonna Need It: don't build for requirements you only imagine.

They pull against SOLID and patterns on purpose: principles tell you how to make code flexible; these tell you when flexibility isn't worth its cost.

The problems they solve

  • Without DRY, the VAT rate is 0.2 in the cart, the invoice, and the refund code. It changes; two get updated; refunds are now wrong.
  • Without KISS, a three-field settings form is built on a plugin system with an event bus because "it might grow".
  • Without YAGNI, a team spends a sprint on multi-currency support for a product that only ever sells in one country — and then has to maintain it forever.

Think of it like

Packing for a weekend trip. DRY: one list, not three slightly different lists on three scraps of paper. KISS: a backpack, not a modular luggage system. YAGNI: don't pack the snow boots for the beach "in case". You can buy boots if it actually snows.

DRY is about knowledge, not text

Two lines that look the same aren't necessarily duplication. If they'd change for different reasons, merging them couples two unrelated rules — the bug from Single Responsibility. Ask: if this changes, must the other change too? Only then are they the same knowledge.

A useful guard: the rule of three — tolerate a second copy; extract on the third, when you can see what's genuinely shared.

DRY: every caller reads one source of truth

Watch it

Hands on

The shop below repeats its discount knowledge. Someone raised the member discount to 15% in one place and missed the other, so the receipt and the charged amount disagree. Make the rule live in one place so both lines print the same correct price.

Fix it: two copies of one rule drifted apart
def cart_total(prices, member):
    total = sum(prices)
    if member:
        total *= 0.85          # updated to 15% off
    return round(total, 2)

def receipt_line(prices, member):
    total = sum(prices)
    if member:
        total *= 0.90          # still the old 10% — nobody remembered this copy
    return f"You pay {round(total, 2):.2f}"


prices = [20.0, 30.0]
print(f"charged {cart_total(prices, True):.2f}")
print(receipt_line(prices, True))
output
charged 42.50
You pay 42.50

Run and edit it in the app.

KISS and YAGNI in practice

  • Write the straightforward version first; let real change requests show you where flexibility is needed.
  • A pattern is a cost you pay for a specific flexibility. If you can't name the change it enables, skip it.
  • Leave code easy to change — small functions, tests, clear names — instead of pre-building the change. That's the cheap insurance.
  • YAGNI is about features and abstractions, not quality. Tests, error handling, and security aren't speculative.

validate_username() and validate_tag() both check len(x) <= 20 today. Product says usernames may become 30 soon; tags won't change. Should you merge them into one function?

Which is the clearest YAGNI violation?

Pros and cons

ProsCons when misapplied
DRYOne place to change a ruleOver-merging couples unrelated rules
KISSCode anyone can read"Simple" can become "naive" for real complexity
YAGNINo time spent on unused featuresIgnoring a known, imminent need costs a rewrite

How it relates

Key terms

  • DRY — Each piece of knowledge has a single, authoritative representation.
  • KISS — Prefer the simplest design that clearly solves the problem.
  • YAGNI — Don't build functionality until it's actually needed.
  • Rule of three — Tolerate duplication once; extract the shared part on the third occurrence.