Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Low-Level Design (Object-Oriented Design)  Module 4 – Design principles: SOLID and beyond

DRY, KISS and YAGNI without dogma

DRY, KISS and YAGNI as their sources define them: duplicated knowledge, not look-alike code; fewest elements; and features built only when needed.

  • Beginner
  • 20 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7 and Node.js 24.21.0
  • By MySmartCoPilot
Free lesson, Pro answers: 20 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Apply DRY to duplicated knowledge, not to code that merely looks similar
  • Recognise the wrong abstraction and undo it by inlining
  • Choose the simplest design that passes the tests, using Kent Beck's four rules
  • Weigh a speculative feature against Fowler's costs of build, delay, carry and repair

Before you start

What you’ll learn · Before you start

What you will learn

  • Apply DRY to duplicated knowledge, not to code that merely looks similar
  • Recognise the wrong abstraction and undo it by inlining
  • Choose the simplest design that passes the tests, using Kent Beck's four rules
  • Weigh a speculative feature against Fowler's costs of build, delay, carry and repair

Before you start

On this page

DRY (“don’t repeat yourself”), KISS (“keep it simple”) and YAGNI (“you aren’t gonna need it”) are the three slogans quoted most often in design discussions, and they are misused just as often. In the forms their sources give them, each is precise. DRY is about knowledge, not about text. Simple means the fewest elements that pass the tests and show their intent, not the fewest lines. YAGNI means building what today’s requirements ask for while keeping the code easy to change. This lesson runs an example of each, including the bug that the most common misuse of DRY causes.

DRY is about knowledge, not text

Andy Hunt and Dave Thomas named the principle in The Pragmatic Programmer, and defined it like this:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

In the book’s second edition they say that many readers of the first took DRY to mean “don’t copy-and-paste lines of source”, and that this is only a small part of it. Their test is about change: when one fact changes, do you have to make that change in several places, perhaps in several formats? Then the fact is duplicated. A college library allows each member three books at a time. If can_borrow(), borrow() and the holdings report each contain the number 3, the rule exists three times. When the library allows four, someone must find all three copies, and the one they miss gives a member a fourth book at the desk while the report still says “3 of 3”.

Knowledge also hides outside code. A limit stated by hand in a help page and enforced in a function is one fact in two places, and so is a database column added by hand both to a table and to the class that maps it. The cure is the same each time: one authoritative place, a constant, a table or a schema, and everything else derived from it or reading it.

Code that only looks the same

The opposite mistake is to treat look-alike code as duplication. The same college charges a late fine in two places. The library charges for books returned late: two days free, then 5 a day. The sports room charges for kit, such as bats and rackets, returned late: two days free, then 5 a day. Someone notices the two identical functions and merges them into one late_fine() “to stay DRY”. Then the library decides that no book should cost more than 50 in fines, and the developer adds the cap to the shared function. Each owner’s checks, run against the merged design and against two separate functions:

Two look-alike rules, merged and kept apart, after one of them changed

lookalike/check.py

"""Each owner's checks, run against both designs after the library capped book fines at 50."""

import fines_merged
import fines_separate

CHECKS = [
    ("library", "book_fine", 30, 50),  # capped: 28 chargeable days would be 140
    ("library", "book_fine", 5, 15),
    ("sports", "kit_fine", 30, 140),  # the sports room never asked for a cap
    ("sports", "kit_fine", 5, 15),
]

for design in (fines_merged, fines_separate):
    print(f"{design.__name__}:")
    for owner, function, days, expected in CHECKS:
        got = getattr(design, function)(days)
        verdict = "ok" if got == expected else f"WRONG, the {owner} rule says {expected}"
        print(f"  {owner:8} {function}({days}) = {got:<4} {verdict}")

Output

fines_merged:
  library  book_fine(30) = 50   ok
  library  book_fine(5) = 15   ok
  sports   kit_fine(30) = 50   WRONG, the sports rule says 140
  sports   kit_fine(5) = 15   ok
fines_separate:
  library  book_fine(30) = 50   ok
  library  book_fine(5) = 15   ok
  sports   kit_fine(30) = 140  ok
  sports   kit_fine(5) = 15   ok

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 check.py

lookalike/fines_merged.py

"""The college's two late fines after someone merged them "to stay DRY", and then applied the library's new cap."""

FREE_DAYS = 2
PER_DAY = 5
CAP = 50  # the library's new rule: no book costs more than 50 in fines


def late_fine(days_late):
    """Used by the library for books and by the sports room for kit."""
    return min(CAP, max(0, days_late - FREE_DAYS) * PER_DAY)


def book_fine(days_late):
    return late_fine(days_late)


def kit_fine(days_late):
    return late_fine(days_late)

lookalike/fines_separate.py

"""The same two fines kept apart, because they belong to two owners who change them for their own reasons."""

# The library's rule, owned by the librarian.
BOOK_FREE_DAYS = 2
BOOK_PER_DAY = 5
BOOK_CAP = 50  # the library's new rule


def book_fine(days_late):
    return min(BOOK_CAP, max(0, days_late - BOOK_FREE_DAYS) * BOOK_PER_DAY)


# The sports room's rule, owned by the sports teacher. It looks the same as the library's old rule, by coincidence.
KIT_FREE_DAYS = 2
KIT_PER_DAY = 5


def kit_fine(days_late):
    return max(0, days_late - KIT_FREE_DAYS) * KIT_PER_DAY

The library’s checks pass in both designs. In the merged one, a kit returned 30 days late now costs 50 instead of 140, a change the sports room never asked for and will not notice until someone complains. The two functions were never one piece of knowledge: they belong to two owners, who change them for their own reasons, as the lesson on the Single Responsibility Principle put it. The Pragmatic Programmer makes the same point with two validation functions whose bodies happen to match: the code is the same, the knowledge is not, and the match is a coincidence.

One borrowing rule copied into three functions is merged into one constant; two fine rules that look alike stay separate.1. One rule in three places: duplication2. Two rules that look alike: coincidenceRule: a member holdsat most 3 bookscan_borrow()literal 3borrow()literal 3holding_report()literal 3Fix: BORROW_LIMIT = 3,read by all threeLibrary ruleowned by the librarianSports-room ruleowned by the sports teacherbook_fine()2 days free, then 5 a daykit_fine()2 days free, then 5 a dayKeep both: they changefor different reasons

Duplicated knowledge, and two rules that only look alike

Text description of the diagram

The diagram shows two situations, one above the other.

  1. One rule in three places: the rule that a member holds at most 3 books is written as the literal 3 in can_borrow(), in borrow() and in holding_report(). That is duplicated knowledge, and the fix merges the three copies into one constant, BORROW_LIMIT = 3, which all three functions read.
  2. Two rules that look alike: the library's rule, owned by the librarian, becomes book_fine(); the sports room's rule, owned by the sports teacher, becomes kit_fine(). Today both say 2 days free, then 5 a day. Both are kept, because they change for different reasons: the code is the same by coincidence, not because it represents one piece of knowledge.

The wrong abstraction

Sandi Metz wrote that “duplication is far cheaper than the wrong abstraction”, and described how such an abstraction grows. Someone extracts the duplicated code into a shared function. Later a new case almost fits it, so the function gets a parameter and a condition. Then another case, another parameter, another condition, until nobody can read it or change it safely. Her way out is to go back: copy the shared code into each caller again, delete the parts each caller does not use, and only then look for what is really shared.

A guideline that prevents most of this is the rule of three, which Martin Fowler’s book Refactoring credits to Don Roberts: the first time you write something, just write it; the second time, notice the repetition and write it again anyway; the third time, extract it. It is a heuristic, not a law. Two copies cost little, and waiting shows whether they change together. If they do, you have found one piece of knowledge and can give it one home; if they drift apart, you have saved yourself a function with a flag.

Common mistake

A utils.py that collects every helper that looks like another is the coincidental cohesion of the first lesson in this module. Before you extract shared code, name the one fact it represents and its one owner. If you cannot, it is not shared knowledge yet.

KISS: fewer concepts, not fewer lines

“Keep it simple” is easy to agree with and hard to apply, because it does not say simple for whom. Kent Beck’s four rules of simple design, which Martin Fowler summarises as passes the tests, reveals intention, no duplication and fewest elements, give it an order of priority. The code first has to work. Then a reader must be able to see what it is for; a clever one-line comprehension that takes a minute to decode loses to a plain loop here. Then no fact may be stated twice, which is DRY. Only last come the fewest classes, functions and names.

That order settles most arguments. Shorter is not simpler if it hides intent, and a design with extension points that nothing uses fails the last rule however clean each piece looks. The simplest design is the one with the fewest concepts a reader has to learn to trust it.

YAGNI: build what is needed now

The canteen at the same college has one pricing rule: lunch costs 10 % more from 12:00 to 14:00. One version of the code expects many more rules one day, and builds a rule interface, a plugin registry, a configuration format and a pipeline that applies the configured rules in order. Another version is a function with an if. Both get the same six checks, and then this program measures them from their source:

A pricing framework for one rule, against a function

yagni/compare.py

"""Runs the same checks against both pricing modules, then measures each one's size from its source."""

import ast
from pathlib import Path

import plain
import speculative

CHECKS = [  # (base price in paise, hour) -> price in paise
    ((4000, 11), 4000),
    ((4000, 12), 4400),
    ((4000, 13), 4400),
    ((4000, 14), 4000),
    ((2550, 12), 2805),
    ((0, 13), 0),
]


def passes(module):
    return sum(module.price(*args) == expected for args, expected in CHECKS)


def size(module):
    source = Path(module.__file__).read_text(encoding="utf-8")
    tree = ast.parse(source)
    docstrings = set()
    for node in ast.walk(tree):
        if isinstance(node, (ast.Module, ast.ClassDef, ast.FunctionDef)) and ast.get_docstring(node) is not None:
            first = node.body[0]
            docstrings.update(range(first.lineno, first.end_lineno + 1))
    code_lines = [
        number
        for number, line in enumerate(source.splitlines(), start=1)
        if line.strip() and not line.strip().startswith("#") and number not in docstrings
    ]
    classes = sum(isinstance(node, ast.ClassDef) for node in ast.walk(tree))
    functions = sum(isinstance(node, ast.FunctionDef) for node in ast.walk(tree))
    return len(code_lines), classes, functions


for module in (speculative, plain):
    print(f"{module.__name__}.py passes {passes(module)} of {len(CHECKS)} checks")
print(f"{'':16}{'lines of code':>15}{'classes':>10}{'functions':>11}")
for module in (speculative, plain):
    lines, classes, functions = size(module)
    print(f"{module.__name__ + '.py':16}{lines:>15}{classes:>10}{functions:>11}")

Output

speculative.py passes 6 of 6 checks
plain.py passes 6 of 6 checks
                  lines of code   classes  functions
speculative.py               44         5         12
plain.py                      5         0          1

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 compare.py

yagni/speculative.py

"""Canteen pricing, built for rules that might come one day: a plugin registry, rules read from configuration and a
pipeline that applies them in order. Only one rule exists: lunch costs 10 % more from 12:00 to 14:00."""

from abc import ABC, abstractmethod
from dataclasses import dataclass, field


@dataclass(frozen=True)
class PricingContext:
    base_paise: int
    hour: int
    extras: dict = field(default_factory=dict)


class PricingRule(ABC):
    @abstractmethod
    def applies(self, context: PricingContext) -> bool: ...

    @abstractmethod
    def adjust(self, price: int, context: PricingContext) -> int: ...


class RuleRegistry:
    def __init__(self):
        self._rules = {}

    def register(self, name):
        def decorator(cls):
            self._rules[name] = cls
            return cls

        return decorator

    def build(self, config):
        return [self._rules[entry["rule"]](**entry.get("options", {})) for entry in config]


registry = RuleRegistry()


@registry.register("peak-hours")
class PeakHourRule(PricingRule):
    def __init__(self, start=12, end=14, percent=10):
        self.start, self.end, self.percent = start, end, percent

    def applies(self, context):
        return self.start <= context.hour < self.end

    def adjust(self, price, context):
        return price + price * self.percent // 100


class PricingPipeline:
    def __init__(self, rules):
        self._rules = list(rules)

    def price(self, context):
        price = context.base_paise
        for rule in self._rules:
            if rule.applies(context):
                price = rule.adjust(price, context)
        return price


CONFIG = [{"rule": "peak-hours", "options": {"start": 12, "end": 14, "percent": 10}}]
_pipeline = PricingPipeline(registry.build(CONFIG))


def price(base_paise, hour):
    return _pipeline.price(PricingContext(base_paise, hour))

yagni/plain.py

"""Canteen pricing for the one rule that exists: lunch costs 10 % more from 12:00 to 14:00."""

PEAK_HOURS = range(12, 14)


def price(base_paise, hour):
    if hour in PEAK_HOURS:
        return base_paise + base_paise // 10
    return base_paise

Both pass every check. One needs 44 lines of code, 5 classes and 12 functions to do what the other does with 5 lines and one function. Martin Fowler’s note on YAGNI, a practice from Extreme Programming, names what the extra code costs. The cost of build is the work spent on it, wasted if the predicted rules never come. The cost of delay is the needed features that waited while it was built. The cost of carry is the extra complexity that every later change has to work around, even if the prediction was right. The cost of repair comes when the rules do arrive and turn out different from the guess, so the framework has to be reworked anyway.

Fowler is careful about what YAGNI does not cover: it never argues against making code easier to change. Refactoring, tests and small, clear units are what make it safe to wait. When the second pricing rule arrives, the plain version turns into a seam in a few minutes, as the lesson on the Open/Closed Principle did for vehicle fees. And when a requirement does say that rules will change often, for example that the canteen committee sets them every month without a release, the registry is no longer speculation and earns its place.

Using the three together

DRY, KISS and YAGNI side by side
Criterion DRYKISSYAGNI
The question it asks Is one fact stated in more than one place?Is there a design with fewer concepts that still passes the tests and shows its intent?Does a requirement ask for this now?
What it is not A ban on similar-looking codeA contest for the fewest linesA reason to skip tests or refactoring
Typical misuse Merging two owners’ rules into one function with flagsClever one-liners that hide intentRefusing a seam that a stated requirement needs
When it gives way Across boundaries whose owners change for different reasonsWhen a stated requirement needs the extra conceptWhen the cost of adding the feature later is known to be high

The three pull in the same direction most of the time: one home for each fact, as few concepts as the requirements allow, and nothing built for a guessed future. When they disagree, for example a seam that YAGNI calls premature and a change that the requirements say is coming, the next lessons of this module show how to argue the case.

In a design interview

Say which repetition you are removing and which you are keeping: “the fee per hour is one constant used by the gate and the receipt; the fine rules for bikes and cars stay separate because different people set them”. Then say what you are not building and why: “no plugin system for one tariff; if a second tariff comes, fee becomes a strategy”. It shows judgement, which is what the follow-up questions test.

Text Diff Paste fines_merged.py and fines_separate.py side by side to see how little the two designs differ in text, and how much in meaning. Python Online Compiler Add a second pricing rule to plain.py and see how small the change is.

Interview questions

Warm-up (fresher to mid level): what does DRY mean, exactly, and what does it not mean? DRY, from The Pragmatic Programmer, says that every piece of knowledge should have a single, unambiguous, authoritative representation in a system: a business rule, a limit or a data format should live in one place that everything else reads or derives from. The test is a change: if one fact changing forces edits in several places, the fact is duplicated, whether the copies are in code, documents or schemas. DRY does not mean that similar-looking code must be merged. Two functions with the same body can represent two different rules with different owners, and merging them couples those owners, so a change for one breaks the other. Duplicated text is a reason to ask whether the knowledge is shared, not a reason to extract a function.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Mid to senior

    Six months ago a colleague merged two near-identical 40-line functions, for domestic and international shipping fees, into one shipping_fee() with three boolean flags. Now almost every change for one kind of shipment breaks the other. What do you do, step by step, and how do you stop it happening again?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    Before the first discount rule shipped, your team spent three weeks building a plugin framework for discount rules. A year later there are two rules, and each change to them takes about twice as long as it should. How do you judge whether that work paid off, and how would you decide next time?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • DRY is about knowledge: one fact, one authoritative place. Test it by asking how many places one change touches.
  • Identical code can be two pieces of knowledge; merging two owners’ rules couples them and breaks one when the other changes.
  • The wrong abstraction costs more than duplication. Undo it by inlining, and wait for a third case before extracting.
  • Simple means Beck’s order: passes the tests, reveals intention, no duplication, fewest elements.
  • YAGNI: build for today’s requirements, keep the code easy to change, and count the costs of build, delay, carry and repair before building for a guess.

Exercise

Exercise · Easy · Python

Give one rule one home, and keep two look-alikes apart

A college hostel's code has two kinds of repetition, and only one of them is duplication.

  1. The rule "a resident may have at most 2 guest nights a month" is written in three functions: can_add_guest_night(), add_guest_night() (with its error message) and guest_summary(). Give the rule one authoritative representation, a module constant GUEST_NIGHTS_LIMIT, that all three read when they run, so that changing the constant changes the check, the booking, the message and the summary together. The number 2 should then appear in the module only once.
  2. The mess committee has a new rule: a mess late charge never goes above 100. Apply it. The laundry charge must not change. It belongs to the laundry contractor, who sets it for other reasons, and it only looks like the mess rule today.

The sample tests check today's behaviour, change GUEST_NIGHTS_LIMIT to 3 and check all three functions again, count the 2s in your source, and check both charges.

Starter code · hostel_rules.py

"""A college hostel's rules, as the first version wrote them. See the exercise prompt for what to change."""


def can_add_guest_night(nights_this_month):
    return nights_this_month < 2


def add_guest_night(resident, guest):
    if len(resident["guest_nights"]) >= 2:
        raise ValueError(f"{resident['name']} has used all 2 guest nights this month")
    resident["guest_nights"].append(guest)


def guest_summary(residents):
    return [f"{r['name']}: {len(r['guest_nights'])} of 2 guest nights" for r in residents]


def mess_late_charge(days_late):
    """The mess committee's rule for paying the mess bill late."""
    return max(0, days_late - 3) * 10


def laundry_late_charge(days_late):
    """The laundry contractor's rule for collecting clothes late."""
    return max(0, days_late - 3) * 10
The sample tests · test_hostel_rules.py
import ast
import inspect

import hostel_rules
from hostel_rules import add_guest_night, can_add_guest_night, guest_summary, laundry_late_charge, mess_late_charge


def resident(name, nights=()):
    return {"name": name, "guest_nights": list(nights)}


def test_guest_nights_today():
    """a resident may have 2 guest nights a month, in all three places"""
    assert can_add_guest_night(1) is True
    assert can_add_guest_night(2) is False
    anu = resident("Anu", ["cousin"])
    add_guest_night(anu, "sister")
    try:
        add_guest_night(anu, "friend")
    except ValueError as error:
        assert "all 2 guest nights" in str(error)
    else:
        raise AssertionError("a third guest night must be refused")
    assert guest_summary([anu, resident("Bilal")]) == ["Anu: 2 of 2 guest nights", "Bilal: 0 of 2 guest nights"]


def test_the_limit_changes_in_one_place():
    """setting GUEST_NIGHTS_LIMIT changes the check, the booking, its message and the summary"""
    saved = getattr(hostel_rules, "GUEST_NIGHTS_LIMIT", None)
    hostel_rules.GUEST_NIGHTS_LIMIT = 3
    try:
        assert can_add_guest_night(2) is True
        assert can_add_guest_night(3) is False
        anu = resident("Anu", ["cousin", "sister"])
        add_guest_night(anu, "friend")
        try:
            add_guest_night(anu, "neighbour")
        except ValueError as error:
            assert "all 3 guest nights" in str(error)
        else:
            raise AssertionError("a fourth guest night must be refused once the limit is 3")
        assert guest_summary([anu]) == ["Anu: 3 of 3 guest nights"]
    finally:
        hostel_rules.GUEST_NIGHTS_LIMIT = saved


def test_the_limit_is_written_once():
    """the number 2 appears once in the module: the constant itself"""
    tree = ast.parse(inspect.getsource(hostel_rules))
    twos = [node for node in ast.walk(tree) if isinstance(node, ast.Constant) and node.value == 2]
    assert len(twos) == 1


def test_mess_charge_is_capped_at_100():
    """the mess committee's new rule: a mess late charge never goes above 100"""
    assert mess_late_charge(3) == 0
    assert mess_late_charge(4) == 10
    assert mess_late_charge(13) == 100
    assert mess_late_charge(40) == 100


def test_laundry_charge_is_unchanged():
    """the laundry contractor's rule looks the same, but it was never capped"""
    assert laundry_late_charge(3) == 0
    assert laundry_late_charge(4) == 10
    assert laundry_late_charge(40) == 370
A hint

The functions must read GUEST_NIGHTS_LIMIT each time they run, so use the module-level name inside each function body and in the f-strings; a default argument such as limit=GUEST_NIGHTS_LIMIT would freeze the value when the module loads. For the charges, resist a shared late_charge() helper: give each owner's rule its own constants, and the cap goes only into the mess rule.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Check yourself

6 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 6 What does "don't repeat yourself" ask for, in the words of the book that named it?

    Choose one answer.

    Show the answer to question 1

    Answer: Every piece of knowledge has a single, unambiguous, authoritative representation within a system

    The Pragmatic Programmer defines DRY in terms of knowledge, and its second edition says that reading it as "don't copy and paste lines of source" misses most of it. Duplicated knowledge can hide in code that looks different, such as a limit written once in the code and once in a document, and identical code can represent two different pieces of knowledge.

  2. Question 2 of 6 The library capped book fines at 50 and the developer changed the shared late_fine(). What does check.py print?

    What does this program print? Choose one answer.

    """Each owner's checks, run against both designs after the library capped book fines at 50."""
    
    import fines_merged
    import fines_separate
    
    CHECKS = [
        ("library", "book_fine", 30, 50),  # capped: 28 chargeable days would be 140
        ("library", "book_fine", 5, 15),
        ("sports", "kit_fine", 30, 140),  # the sports room never asked for a cap
        ("sports", "kit_fine", 5, 15),
    ]
    
    for design in (fines_merged, fines_separate):
        print(f"{design.__name__}:")
        for owner, function, days, expected in CHECKS:
            got = getattr(design, function)(days)
            verdict = "ok" if got == expected else f"WRONG, the {owner} rule says {expected}"
            print(f"  {owner:8} {function}({days}) = {got:<4} {verdict}")
    Show the answer to question 2

    Answer: it prints

    fines_merged:
      library  book_fine(30) = 50   ok
      library  book_fine(5) = 15   ok
      sports   kit_fine(30) = 50   WRONG, the sports rule says 140
      sports   kit_fine(5) = 15   ok
    fines_separate:
      library  book_fine(30) = 50   ok
      library  book_fine(5) = 15   ok
      sports   kit_fine(30) = 140  ok
      sports   kit_fine(5) = 15   ok

    In the merged design both fines run through late_fine(), so the library's cap reaches the sports room, which never asked for it: a kit 30 days late now costs 50 instead of 140. Kept separate, each owner's rule changes on its own.

  3. Question 3 of 6 Which of these are duplicated knowledge in the sense of DRY?

    Choose every answer that is right.

    Show the answer to question 3

    Answer:

    • A help page that states the borrowing limit, and the code that enforces it, both written by hand
    • The same service tax percentage typed as a number in three different files
    • A database schema and a class whose fields must be edited by hand together for every new column

    The first three express one fact in several places, so one change needs several edits, which is the book's acid test. Two functions owned by different teams may be identical today and still be two pieces of knowledge, and two loops share only a language construct.

  4. Question 4 of 6 Martin Fowler lists four costs of building a feature before it is needed. Which one describes extra code making every other change slower?

    Choose one answer.

    Show the answer to question 4

    Answer: The cost of carry

    The cost of build is the effort spent on something that may never be needed, the cost of delay is the needed work it pushed back, and the cost of repair applies when the guessed feature turns out wrong. The cost of carry is the extra complexity the code adds to every later change while it waits, which applies even if the guess was right.

  5. Question 5 of 6 Using Kent Beck's rules of simple design, which version of a function is the simplest?

    Choose one answer.

    Show the answer to question 5

    Answer: The one that passes the tests, shows its intent, has no duplicated knowledge and has the fewest elements

    Beck's rules are in order of priority: pass the tests, reveal intention, no duplication, fewest elements. Fewer lines bought with clever, hard-to-read code fails the second rule, and unused extension points fail the fourth.

  6. Question 6 of 6 Two near-identical blocks of code appear for the first time, in parts of the program with different owners. What is the safest default?

    Choose one answer.

    Show the answer to question 6

    Answer: Leave them separate for now and extract only once a shared piece of knowledge is clear, for example at a third case

    Waiting costs little while there are two copies, and it shows whether they change together. Extracting at once risks the wrong abstraction that Sandi Metz describes: a shared function that grows a parameter and a condition for every case it almost fits.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.