Comments and documents drift out of sync with the code they describe. Explain the mechanism behind this drift and the techniques that keep explanatory material trustworthy over time.
answer
- verification pressure: types > tests > names > comments > wiki
- rot = code forced through checks, prose is not
- stale comment worse than none (reader acts on it)
- one owner per fact: VCS / tracker / ADR / code
- co-locate, minimise, automate (doctests, generated refs, link check)
basics
~20 sCode is verified by compilers and tests; prose is verified by nobody. So edits update the code and skip the comment, and the comment quietly becomes false. Fixes: fewer comments, put facts in code/tests/types, and review comments as code.
solid answer
~60 s**Mechanism.** Every artifact has a *verification pressure*. Code is exercised at build and run time, so errors surface. Prose has none, so a comment only fails when a human notices — often after acting on it. Under normal editing, code moves and prose stays: this asymmetry is comment rot. It compounds because a codebase's stale comments are indistinguishable from accurate ones, so readers eventually discount all of them. **Countermeasures, strongest first:** (1) express the fact in a *checked* medium — types, named constants, an extracted function, an assertion, a test; (2) keep a single owner per fact (version control for history, issue tracker for TODOs, ADRs for decisions) so there is nothing to desynchronise; (3) prefer comments about *why*, which change far more slowly than mechanics; (4) co-locate — a comment beside the line it describes is more likely to be updated than a document in a wiki; (5) automate what you can — doc-comment linting, executable/doctest examples, generated API reference, links checked in CI; (6) make comment updates a review expectation, and delete comments you cannot verify.
go deeper
Say comments are not checked by the compiler or tests, so edits leave them behind; keep few comments and update the ones you touch.
Explain the asymmetry explicitly and give practical fixes: encode facts in names, types and tests; delete comments that merely restate code; update comments in the same commit.
Present the verification-pressure hierarchy, single-ownership of each fact, why-over-what as a rot-rate choice, and automation (doctests, generated reference, link checking, TODO lint).
Design the system of record across an organisation — ADRs, docs-as-code in the same repo and CI, ownership and review gates — and account for the irreducible case that rationale cannot be machine-verified.
## The mechanism, precisely Think of every statement about a system as living in a medium with a certain **verification pressure** — how quickly a false statement in that medium is detected. | Medium | Who checks it | Detection latency | |---|---|---| | Type signature | Compiler / type checker | Immediate | | Executable test | Test runner in CI | Minutes | | Assertion / contract | Runtime, in tests or production | Minutes to days | | Function/variable name | Nobody mechanically, but tools rename it consistently and reviewers read it | Slow, but drift is visible | | Inline comment | A human who happens to read it | Months, or never | | Wiki page / design doc | A human who happens to open it | Often never | **Comment rot** is the direct consequence: an edit that changes behaviour is forced through the checked media (it must compile, tests must pass) but is not forced through the unchecked ones. Nothing errors when the comment above the changed line is now wrong. Repeat over hundreds of commits and years of turnover, and a meaningful fraction of prose in any large codebase is false. Two compounding effects make this worse than it sounds: - **Indistinguishability.** A stale comment looks exactly like a correct one. There is no visual marker, so readers cannot filter. The rational response is to distrust all comments, which destroys the value of the good ones. - **Negative value.** A wrong comment is worse than no comment. A reader with no comment investigates; a reader with a confident, wrong comment acts on it. Stale comments have caused production incidents ("the doc said this endpoint was idempotent"). ## Countermeasures, ordered by strength **1. Move the fact into a checked medium.** The most durable fix is to stop stating it in prose at all. - "must not be null" → a non-nullable type. - "in milliseconds" → `timeoutMs`, or a `Duration` type. - "only positive values allowed" → validation in a value object's constructor, plus a test. - "this handles the leap-year edge case" → a test named for that case, which fails if the handling is removed. - "this block validates the request" → an extracted `validateRequest()` function. Each of these converts a hope into an enforcement. **2. Single ownership of each fact.** Rot requires two copies to diverge; one copy cannot desynchronise. Assign each kind of knowledge one authoritative home: version control owns change history and deleted code; the issue tracker owns planned work; **Architecture Decision Records (ADRs)** own significant decisions and their context and consequences; generated API reference owns public signatures; the code owns behaviour. Then *link* rather than restate — a comment saying `// see ADR-021` stays true even as the ADR evolves. **3. Prefer WHY over WHAT.** Mechanics churn constantly; rationale, constraints and hazards change rarely. A comment about a vendor's broken contract can be accurate for years, while a comment describing a loop is one refactor from wrong. Choosing the slow-changing subject matter buys you a much lower rot rate for free. **4. Co-locate and minimise.** Distance predicts rot: a comment on the line rots slower than one at the top of the file, which rots slower than a README, which rots slower than a wiki page in another system. Same for volume — a file with three high-value comments gets them updated; a file with two hundred does not. Fewer, closer, denser. **5. Automate verification where possible.** - **Executable examples**: doctests, or example snippets compiled/run as tests, so a wrong example breaks the build. - **Generated reference**: publish API docs from the signatures rather than hand-copying them. - **Doc linting**: tools that fail the build when a documented parameter no longer exists, or when a doc comment is missing on a public symbol. - **Link checking** in CI so references to tickets, ADRs and pages do not dangle. - **TODO hygiene rules**: require an issue reference, and flag TODOs whose issue is closed. **6. Social process.** Make "did this change invalidate any nearby comment or doc?" an explicit review question, and give reviewers standing to delete unverifiable prose. Treat documentation edits as part of the same commit, not a follow-up (docs-as-code: same repository, same review, same CI). ## Trade-offs and edge cases - **You cannot mechanise rationale.** No tool verifies "we chose this because of a benchmark". These comments still rot when the reason expires — for example the vendor fixes their API. Mitigation: date them or tie them to a ticket, so a reader can check whether the premise still holds. - **Deleting doubtful comments has a cost.** Sometimes a half-true comment is the only surviving trace of a real constraint. The safer move for a nontrivial one is to investigate and rewrite it, or to demote it to a question in review, rather than silently deleting. - **Generated docs are only as good as the signatures.** A published reference that faithfully renders meaningless parameter names is accurate and useless. - **Over-rotation to "no docs"**: some teams conclude that because docs rot, they should not write them. The result is knowledge concentrated in a few people's heads — a much worse failure, and one with no detection mechanism at all. The summarising rule: **prefer the most-verified medium that can hold the fact; when only prose can hold it, keep it short, close, singly-owned, and reviewed like code.**
- Why is a stale comment often described as worse than having no comment at all?Absence of information prompts a reader to investigate the code; false information prompts them to act with unwarranted confidence. Because stale comments are visually indistinguishable from correct ones, they also erode trust in every other comment in the codebase.
- What role do Architecture Decision Records play in reducing rot compared with inline comments?An ADR gives each significant decision a single dated home with context, options considered and consequences. Code then links to it instead of restating it, so there is only one copy to keep current, and superseding a decision is an explicit new record rather than an edit that may miss scattered copies.
A comment is a hand-written label on a warehouse shelf; the code is the stock itself. Every restock changes the stock and nobody re-writes the labels, so eventually people stop trusting labels and open every box. Barcode-scanning the stock — types, tests, generated docs — is what keeps the labels honest.
saying these in an interview costs you the question
- "Documentation rots, so don't write any" — replaces a detectable problem with undetectable tribal knowledge.
- Duplicating a function signature or parameter list in prose that must be hand-maintained.
- Assuming a wiki page is current because it exists; unowned pages have the highest rot rate of all.
- Treating doc updates as a follow-up ticket rather than part of the same change.
- Believing generated API docs are automatically useful — they are accurate but only as informative as the names behind them.