Quiz — Chapter 24: Code Documentation

Target: 70%+ before moving on. This quiz checks whether you can tell a what-comment from a why-comment, judge a docstring's contract, reason about type hints and self-documenting code, and place code on the documentation spectrum. Answers and explanations are hidden — try each before revealing.


Section 1 — Multiple Choice

1. The single canonical lesson of this chapter is best stated as: - A) Document every line of your code thoroughly. - B) Comment the why, not the what. - C) Good code never needs any comments. - D) Always write a docstring for every function.

Answer **B.** "Comment the why, not the what" (§24.2) is the threshold idea: the code already says *what* it does, so comments exist to capture what the code can't — the *why* (intent, constraints, decisions, workarounds). A is the over-documentation failure (§24.6); C overstates self-documenting code (it handles the *what*, never the *why*, §24.5); D is sometimes good practice but not the chapter's central rule, and "every function" is too absolute.

2. Why is # increment i (next to i += 1) considered a bad comment? - A) It's grammatically incorrect. - B) It restates what the code already says, adding no information. - C) It's too short to be useful. - D) It uses the wrong comment syntax.

Answer **B.** It narrates the *what* — `i += 1` already states, completely, that `i` is incremented. The comment translates the code into English no clearer than the code, so it carries zero information (the software twin of "it is important to note that" from [Ch 3](../../part-01-writing-is-thinking/chapter-03-clarity/index.md)). Length (C) and syntax (D) are irrelevant; the problem is redundancy, not form.

3. Which of these is a genuine why-comment (the kind worth writing)? - A) # loop through the list - B) # set x to 5 - C) # Timeout is 4.7s, not 5: upstream hard-cuts at 5s; leave margin to log first. - D) # return the result

Answer **C.** It captures the *reason* behind a magic value (4.7 vs. 5) and a constraint that exists nowhere in the code (the upstream gateway's behavior). A, B, and D all narrate the *what* — they restate the adjacent line and could be deleted with no loss. The test: does the comment tell you something the code *can't*? Only C does.

4. What is the difference between a comment and a docstring? - A) There's no difference; the terms are interchangeable. - B) A comment is internal (explains a line's why to an implementer); a docstring is external (states the contract to a caller who won't read the body). - C) A docstring is for variables; a comment is for functions. - D) A comment is checked by tools; a docstring is not.

Answer **B.** A comment explains the implementation to someone *reading the body* (the *why* of a line, §24.2); a docstring states the *interface* — summary, params, return, errors — to someone *using* the function without reading it, and tools surface it on hover and in generated docs (§24.3). C is backwards/wrong; D describes type hints (§24.4), not the comment/docstring distinction.

5. In Python, which is the official convention that governs docstrings? - A) JSDoc - B) RFC 2119 - C) PEP 257 - D) PEP 8 only

Answer **C.** PEP 257 is Python's docstring convention (triple quotes, one-line summary, blank line, then elaboration). JSDoc (A) is the JavaScript convention. RFC 2119 (B) governs requirement keywords like SHALL/SHOULD ([Ch 33](../../part-07-writing-for-specific-fields/chapter-33-writing-for-engineering/index.md)), not docstrings. PEP 8 (D) is Python's *style* guide for code formatting; it references docstrings but PEP 257 is the docstring-specific convention.

6. Why are type hints considered an especially trustworthy form of documentation? - A) They make the code run faster. - B) A tool can check them against the code, so they can't silently rot the way a prose comment can. - C) They are required in Python. - D) They explain why the code makes its decisions.

Answer **B.** A type checker compares the hint against how the function is actually used and what it returns, so a hint that falls out of sync gets flagged — unlike a comment, which can become a lie unnoticed (§24.4). A is false (hints don't affect runtime speed in Python). C is false (Python type hints are optional). D is the key boundary: type hints document the *what* of the data, *never* the why.

7. "Self-documenting code" most accurately means: - A) Code that needs no documentation of any kind. - B) Code so clear (good names, named constants, small functions) that the what needs no comment — which frees comments for the why. - C) Code that automatically generates its own documentation. - D) Code with a comment on every line.

Answer **B.** Self-documenting code makes the *what* self-evident through naming and structure, so *what*-comments become unnecessary (§24.5) — but it cannot express the *why*, so it never means "no documentation at all" (A is the common misreading). C describes doc-generation tools (a different thing); D is the over-documentation failure (§24.6).

8. A comment that says "returns the user's age" sits above a function that now returns a date of birth (the code changed; the comment didn't). This is: - A) A self-documenting comment. - B) A why-comment. - C) Doc drift — a stale comment, which is worse than no comment. - D) Acceptable, since the comment was true when written.

Answer **C.** This is doc drift (§24.6): the comment is now false. It's *worse than no comment* because no comment forces you to read the (always-true) code, whereas a stale comment makes you trust a falsehood and skip the code. D is wrong — "true when written" is no defense once it's a lie. The fix: change comments in the same edit as the code, and prefer drift-proof documentation (names, type hints).

9. On the documentation spectrum, which describes the too much end? - A) The code is a maze; every why must be re-derived. - B) Noise buries signal, comments rot into lies, and the obvious is narrated while the subtle is ignored. - C) Intent and decisions are captured; the what is left to the code. - D) There are exactly the right number of comments.

Answer **B.** Over-documentation (§24.6) has three harms: noise burying the few real whys (training readers to skip comments), the maintenance burden of comments that rot, and effort spent narrating the obvious instead of the subtle. A is the *none* end (also a disaster). C is the calibrated *center* (the target). D is vague and not how the spectrum is framed.

10. You find a block of commented-out code "kept in case we need it later." The chapter's guidance is: - A) Keep it — you might need it. - B) Add a comment explaining it's disabled. - C) Delete it; version control remembers, and if the decision matters, write a one-line why about that. - D) Move it to a separate file.

Answer **C.** Commented-out code is clutter that confuses every reader about whether it should run (§24.6). Version control already preserves the old code, so delete it; if the *reason* for removing it is important, that's a why worth a one-line comment about the decision (not the dead code). A keeps the clutter; B documents a corpse; D just relocates the confusion.

11. Which best captures why "write for your future self" is a more reliable heuristic than "write for other developers"? - A) Future you is more important than your colleagues. - B) Future you is a concrete, imaginable reader — you know exactly how much context you'll have lost and what confusion you'll be in — so it produces specific, useful documentation. - C) Other developers can ask you questions; future you can't. - D) It's not more reliable; both are equally good.

Answer **B.** "Other developers" stays abstract (you don't know who they are or what they know), so the advice is easy to wave away; future-you is concrete — you can picture the exact moment (mid-bug, no context) and the exact help needed (the reason, not the restatement), which is what turns "I should document this" into "I should write *this* sentence" (§24.1). It's [Ch 2](../../part-01-writing-is-thinking/chapter-02-audience/index.md)'s "specific reader" with the reader handed to you. A is a value judgment, not the reasoning; C is backwards.

12. A docstring's job is fully served when: - A) It explains every line of the function body. - B) A caller can use the function correctly from the docstring alone, without reading the body. - C) It is at least three paragraphs long. - D) It lists the function's internal variables.

Answer **B.** The docstring documents the *contract* for callers — summary, params, return, errors — so the body becomes unnecessary for the common case of *using* the function (§24.3). A and D describe internal implementation detail (that's comments' territory, and most of it shouldn't be in a docstring at all); C confuses length with quality (a one-line docstring can be complete).

Section 2 — True/False with Justification

State true or false and justify in one sentence.

T1. "Well-documented code" means "code with lots of comments."

Answer **False.** Comment *density* doesn't measure documentation quality — well-documented code is usually *sparse* with comments (each capturing a real why), with names, types, and docstrings carrying the rest; a comment on every line is typically the over-documentation failure (§24.6).

T2. A type hint can tell a reader why a parameter defaults to "now" rather than to midnight.

Answer **False.** Type hints document the *what* of the data (`base: datetime | None` says what `base` is), never the *why* — the reason for the default is a comment's or docstring's job; this what/why boundary is the crucial limit on type hints as documentation (§24.4).

T3. A stale comment is no worse than having no comment at all.

Answer **False.** A stale comment is *worse*: no comment forces you to read the always-true code, while a wrong comment makes you trust a falsehood and skip the code (§24.6) — which is the strongest argument for fewer, why-only comments and for drift-proof documentation.

T4. If a comment exists only because a variable has a cryptic name, the best fix is to write a clearer comment.

Answer **False.** The best fix is to *rename the variable* so the comment becomes unnecessary (§24.5) — a name documents the *what* everywhere the value is used and can't drift, whereas a comment fixes the symptom while leaving the cryptic name in place.

T5. "Comment the why, not the what" means a docstring should omit the descriptions of what each parameter is.

Answer **False.** The rule governs *internal* comments (narration of lines a reader can see); a docstring's parameter descriptions are *external* — the contract a caller needs and can't get elsewhere — so stating that "what" is exactly the docstring's job (§24.3, and the boundary mirrors §24.4's type-hint logic).

T6. Picking which docstring style to use (Google vs. NumPy vs. Sphinx) matters more than using one consistently.

Answer **False.** Consistency matters far more than the choice — mixing three styles in one codebase is the "elegant variation" failure from [Ch 7](../../part-02-building-blocks/chapter-07-word-choice-tone-voice/index.md) at the documentation level; pick any reasonable one and apply it everywhere (§24.3).

Section 3 — Short Answer

Two to four sentences each.

S1. Explain why a # loop through the items comment and the phrase "it is important to note that" are the same failure, and what Chapter 3 principle covers both.

Model answer + rubric Both are *packaging, not content*: they occupy space and carry no information the reader doesn't already have — the comment restates code the reader can read, and the phrase restates nothing before the real sentence. [Chapter 3](../../part-01-writing-is-thinking/chapter-03-clarity/index.md)'s principle covers both: keep what carries a fact for this reader, cut what's packaging. "Comment the why, not the what" is that same cut applied to code — the *what*-comment is packaging (the code carries that fact), the *why*-comment is content (it carries a fact found nowhere else). **Rubric:** names "no information / packaging" (1); connects to [Ch 3](../../part-01-writing-is-thinking/chapter-03-clarity/index.md)'s keep-the-fact/cut-the-packaging (1); maps it onto the why/what distinction (1).

S2. Name three things a why-comment can capture that the code cannot express, with a one-line example of one.

Model answer + rubric Any three of: *intent* (what the code is trying to accomplish — "Debounce: wait until the user stops typing before hitting the API"), *constraint / reason for a magic value* ("4.7s because the gateway hard-cuts at 5s"), *decision and rejected alternative* ("a list not a set: order matters downstream"), *workaround / warning* ("don't remove the `* 1.0` — it forces float division"), and *a link to outside context* (a ticket, an RFC, a standard). **Rubric:** three distinct categories (1 each, or 2 for three + a correct example).

S3. A teammate says, "Good code is self-documenting, so we shouldn't write comments." Correct them precisely — where are they right, and where wrong?

Model answer + rubric They're right that *what*-comments should go: good names, named constants, and small functions make the *what* self-evident, so narration is clutter (§24.5). They're wrong that *all* comments should go — self-documenting code cannot express the *why* (the reason a timeout is 4.7, a constraint, a decision), which only a comment can hold. The corrected rule: self-documenting code retires the *what*-comments *so that* the *why*-comments can do their irreplaceable job. **Rubric:** concedes the what-comment point (1); names the why-limit of self-documenting code (1); states the corrected synthesis (1).

S4. Why is documentation that a tool can check (type hints, runnable examples, generated docs) safer than free-floating prose comments? Use the word "drift."

Model answer + rubric Checked documentation is *coupled* to the code — a tool compares it against the actual behavior, so it can't fall out of sync without something complaining; prose comments are *decoupled* — nothing ties them to the code, so the code can change while the comment stays frozen and quietly becomes false (doc drift). Drift-proof documentation can't rot in silence; free-floating prose always can, which is why the chapter says to push a fact down into a checked layer when you have the choice (§24.4, §24.6). **Rubric:** coupled vs. decoupled idea (1); "drift" used correctly (1); the practical takeaway, prefer checked layers (1).

S5. Place this scenario on the documentation spectrum and prescribe the fix: "A 60-line file has a comment on every line; the names are all single letters; there are no type hints; and somewhere in the noise is one genuinely important warning about data loss."

Model answer + rubric This is the *too much* end (§24.6), with the added irony that the over-documentation is *causing* harm: the wall of what-comments buries the one data-loss warning that actually matters, and the single-letter names are *forcing* the comments to exist. The fix moves it toward the center: delete the narration, rename the single-letter variables (which retires most comments), add type hints to the signatures, and — critically — make sure the surviving comments include the data-loss warning, now visible because the noise around it is gone. **Rubric:** identifies the *too much* end and the buried-signal harm (1); prescribes delete-narration + rename (1); preserves/surfaces the real warning (1).

Section 4 — Applied Scenario

A short documentation task, graded by rubric.

A1. Document a function end-to-end. Here is an undocumented function from a date-parsing library:

def add_business_days(start, n):
    current = start
    added = 0
    while added < n:
        current = current + timedelta(days=1)
        if current.weekday() < 5:
            added += 1
    return current

Produce a fully documented version that applies the chapter: add type hints to the signature, write a PEP 257 docstring (summary, Args, Returns), and add exactly one why-comment for the one genuinely non-obvious line. Do not add any what-comments.

Model answer + rubric
def add_business_days(start: date, n: int) -> date:
    """Return the date `n` business days after `start`.

    Weekends (Saturday and Sunday) are skipped; only Monday–Friday
    count toward `n`. `start` itself is not counted.

    Args:
        start: The starting date.
        n: The number of business days to advance (>= 0).

    Returns:
        The date `n` business days after `start`.
    """
    current = start
    added = 0
    while added < n:
        current = current + timedelta(days=1)
        # weekday() is 0=Mon..6=Sun, so < 5 means Mon–Fri (a business day).
        if current.weekday() < 5:
            added += 1
    return current
**Rubric (6 points):** - Type hints on the signature (`start: date`, `n: int`, `-> date`) — **1** - One-line summary in the docstring — **1** - `Args` describing both parameters (and the `>= 0` / not-counted nuance) — **1** - `Returns` stating what comes back — **1** - Exactly one *why*-comment, on the genuinely non-obvious line (`weekday() < 5` — the 0=Mon..4=Fri convention that a reader can't be expected to know) — **1** - **No** *what*-comments (no `# loop`, `# add one day`, `# return current`) — **1** 5–6 = excellent (you documented the contract and the one real why, nothing more). 3–4 = re-read §24.2–24.4 (likely a missing contract piece or a stray what-comment). 0–2 = re-read §24.2; you may be narrating the what instead of capturing the why.

A2. Triage a comment review. Below is a function with four comments labeled (a)–(d). For each, state KEEP, DELETE, or REWRITE, and justify in one phrase.

def charge(amount_cents, card):
    # (a) charge the card
    # (b) amount is in cents, not dollars, to avoid floating-point money bugs
    if amount_cents <= 0:                 # (c) check if amount is not positive
        raise ValueError("amount must be positive")
    # (d) Stripe min charge is 50 cents (USD); below this the API rejects it. #payments-220
    if amount_cents < 50:
        raise ValueError("amount below minimum")
    return gateway.charge(amount_cents, card)
Answer + rubric - **(a) DELETE** — narrates the *what* (the function is named `charge`; the line calls `gateway.charge`); pure redundancy. - **(b) KEEP** — a real *why*: explains the cents-not-dollars decision and the reason (float money bugs), which the signature alone can't convey. - **(c) DELETE** — narrates the *what* (`amount_cents <= 0` already says "not positive"); the error message already documents intent. - **(d) KEEP** — a real *why*: the magic number 50 with its reason (Stripe's minimum) and a ticket link; exactly the kind of constraint only a comment can hold. **Rubric (4 pts):** one per correct KEEP/DELETE with a justification that names *what* vs. *why*. (a) and (c) are narration → delete; (b) and (d) carry reasons the code can't → keep. No rewrites are needed here, but marking (a)/(c) as REWRITE earns half credit only if you correctly identify them as narration first.

Scoring & Next Steps

Score What it means Do this
< 50% The why/what line isn't solid yet. Re-read §24.1–24.2 and redo Part A of the exercises (analyze the comments). The whole chapter rests on telling a what-comment from a why-comment.
50–70% You've got the core rule but miss it on harder cases (docstrings, the spectrum, drift). Redo exercises Part B (rewrite what→why) and the §24.6 spectrum questions. Focus on stale comments and self-documenting fixes.
70–85% Solid. You can document code well. Proceed to Chapter 25 (READMEs, API docs, ADRs) — the same "capture the why" instinct, scaled to the project.
> 85% Strong command of the genre. Try exercises Part E (documentation archaeology, the drift experiment, a team convention) and read a real library's docs as a writer.

One-line self-test before moving on: look at the last function you wrote. Can you point to every comment and say "this captures a why the code can't"? If any comment narrates the what, you've found the habit this chapter exists to break.