naming-and-comments — names carry intent; comments carry why
Purpose: names and comments are where code either communicates or hides its
intent. AI agents produce vague names (data, result, handle, manager,
temp, item, process) and comment slop that restates the line below it.
Both are noise; noise degrades every engineer who reads the code after you.
The workspace rule is explicit: the diff is the comment — a comment that
only describes what the code does is banned. Comments must carry why:
rationale, units, invariants, non-obvious trade-offs, links to tickets or
requirements. If the what is unclear, fix the name; don't add a comment to
compensate.
A name that is hard to pick signals unclear design (Ousterhout's red flag:
Hard to Pick Name). Don't push through; investigate the abstraction.
Reflex card (the heuristics)
- Intention-revealing names. A reader should infer purpose without reading
the body. Name by what the thing means in the domain, not its type or
mechanics (
expireStaleSessionsOlderThan not processData).
- Length proportional to scope. A loop-local
i is fine; a module-level
export needs a full, unambiguous name. The wider the scope, the higher the
naming bar.
- Ban noise words.
Manager / Helper / Util / Processor / Handler / Info / Data / Object / temp / obj add syllables and no information. Cut them
or replace them with the actual concept.
- No unexplained abbreviations.
sesExp is not a name. sessionExpiryMs
is. Exception: universally understood acronyms (http, url, id).
- Booleans are predicates.
isActive, hasAccess, canRetry — not
active, access, retry (those read as nouns or verbs, not conditions).
- Functions are verbs; things are nouns.
expireSession() not
sessionExpiry(); SessionCache not ManageSession.
- One term per concept across the codebase. Pick one of
fetch / get / load / retrieve for the same operation and stick to it. Mixed vocabulary
forces readers to wonder if they're different things.
- Named constants for magic literals.
SESSION_EXPIRY_MS = 30 * 60 * 1000
not a bare 1800000. The name is the documentation.
- Comments explain WHY, not WHAT. Document rationale, units, invariants,
gotchas, and non-obvious trade-offs. Delete comments that restate the code.
- A comment apologizing for code means fix the code.
# this is a hack because... → fix the hack, or open a ticket and link it.
- Keep comments next to what they describe; update them with the code.
A stale comment is worse than no comment — it is an active lie.
Red flags
- Single-letter or opaque names outside tiny local scopes.
Manager / Helper / Util / Processor / data / result / temp / obj / item in
any identifier that crosses a function boundary.
- A comment that says exactly what the next line says (
# increment i above
i += 1).
- Commented-out dead code committed to the repo.
- A boolean named as a noun (
active instead of isActive).
- The same concept called three different things in three files.
- A magic number or string literal with no name and no comment explaining it.
- A name you struggled to choose (Ousterhout: Hard to Pick Name — investigate
the design before you commit to any name).
- A
Vague Name (Ousterhout): too imprecise to convey useful information
(handle, process, do).
The procedure
For each new identifier:
- Ask: "Could a stranger reading only this name — no body, no context — guess
what it is and does?" If not, rename.
- Check for noise words and abbreviations; eliminate both.
- Check that the same concept is named consistently elsewhere in the codebase.
For each comment:
- Ask: "Does this add information the code doesn't already carry?" If no,
delete it.
- If the what is unclear, fix the name. Don't add a comment to compensate.
- If the comment is a
# TODO or # hack, either fix it now or convert it
to a tracked ticket and link the ticket number.
When a name is hard to pick: stop naming and investigate the abstraction. A
module with one clear responsibility names itself; one that does two things
can't be named without an And.
Before / after
# BEFORE — vague name, comment restates the code
def proc(d):
# loop through data
for item in d:
if item["ts"] < time.time() - 1800:
del_item(item)
# AFTER — intention-revealing name, comment carries WHY
# 30-minute threshold per §AUTH-112: tokens issued before this window
# cannot be rotated without a full re-auth, so we purge them proactively
# rather than let them accumulate and slow the next gc sweep.
SESSION_EXPIRY_SECS = 30 * 60
def expire_stale_sessions(sessions: list[Session]) -> None:
cutoff = time.time() - SESSION_EXPIRY_SECS
for session in sessions:
if session.issued_at < cutoff:
session_store.delete(session)
Changes: proc → expire_stale_sessions (verb + domain noun); d →
sessions (type-and-domain); item → session; 1800 → SESSION_EXPIRY_SECS
(named constant); comment deleted (restated the loop) and replaced with one that
explains the why — the requirement reference and the gc motivation.
Critique mode
For each identifier: state whether a stranger could infer its purpose from the
name alone. For each comment: state whether it adds information the code doesn't
carry. Recommend rename or delete as appropriate. Tag findings:
[naming-and-comments · vague-name · SEV]
[naming-and-comments · comment-repeats-code · SEV]
[naming-and-comments · hard-to-pick-name · SEV]
hard-to-pick-name findings should also trigger a design investigation —
recommend the caller open a right-sized-design review on the surrounding
abstraction.
References
- Vague Name, Hard to Pick Name, Comment Repeats Code, Nonobvious Code:
../../references/PRINCIPLES.md §B (Ousterhout red flags table)
- Rule 9 ("Names carry intent; comments carry why"):
../../RULES.md
- Workspace house rule: "the diff is the comment" —
../../RULES.md Definition
of Done
- Right-sizing abstractions that produce hard-to-name modules:
../right-sized-design/SKILL.md
1---2name: naming-and-comments3description: Names and comments are the primary channel through which code communicates intent to the next engineer. Use when choosing an identifier ("what should I call this", "rename this", "is this name clear"), deciding whether to add a comment ("should I comment this", "does this need explaining"), or auditing existing prose ("clean up the comments", "too many comments", "comment slop"). Also fires when a name is hard to pick — that difficulty is a design smell, not a vocabulary problem (Ousterhout: Hard to Pick Name).4---56# naming-and-comments — names carry intent; comments carry why78**Purpose**: names and comments are where code either communicates or hides its9intent. AI agents produce vague names (`data`, `result`, `handle`, `manager`,10`temp`, `item`, `process`) and comment slop that restates the line below it.11Both are noise; noise degrades every engineer who reads the code after you.1213The workspace rule is explicit: **the diff is the comment** — a comment that14only describes *what* the code does is banned. Comments must carry *why*:15rationale, units, invariants, non-obvious trade-offs, links to tickets or16requirements. If the *what* is unclear, fix the name; don't add a comment to17compensate.1819A name that is hard to pick signals unclear design (Ousterhout's red flag:20**Hard to Pick Name**). Don't push through; investigate the abstraction.2122## Reflex card (the heuristics)23241. **Intention-revealing names.** A reader should infer purpose without reading25 the body. Name by what the thing *means in the domain*, not its type or26 mechanics (`expireStaleSessionsOlderThan` not `processData`).272. **Length proportional to scope.** A loop-local `i` is fine; a module-level28 export needs a full, unambiguous name. The wider the scope, the higher the29 naming bar.303. **Ban noise words.** `Manager / Helper / Util / Processor / Handler /31 Info / Data / Object / temp / obj` add syllables and no information. Cut them32 or replace them with the actual concept.334. **No unexplained abbreviations.** `sesExp` is not a name. `sessionExpiryMs`34 is. Exception: universally understood acronyms (`http`, `url`, `id`).355. **Booleans are predicates.** `isActive`, `hasAccess`, `canRetry` — not36 `active`, `access`, `retry` (those read as nouns or verbs, not conditions).376. **Functions are verbs; things are nouns.** `expireSession()` not38 `sessionExpiry()`; `SessionCache` not `ManageSession`.397. **One term per concept across the codebase.** Pick one of `fetch / get /40 load / retrieve` for the same operation and stick to it. Mixed vocabulary41 forces readers to wonder if they're different things.428. **Named constants for magic literals.** `SESSION_EXPIRY_MS = 30 * 60 * 1000`43 not a bare `1800000`. The name is the documentation.449. **Comments explain WHY, not WHAT.** Document rationale, units, invariants,45 gotchas, and non-obvious trade-offs. Delete comments that restate the code.4610. **A comment apologizing for code means fix the code.** `# this is a hack47 because...` → fix the hack, or open a ticket and link it.4811. **Keep comments next to what they describe; update them with the code.**49 A stale comment is worse than no comment — it is an active lie.5051## Red flags5253- Single-letter or opaque names outside tiny local scopes.54- `Manager / Helper / Util / Processor / data / result / temp / obj / item` in55 any identifier that crosses a function boundary.56- A comment that says exactly what the next line says (`# increment i` above57 `i += 1`).58- Commented-out dead code committed to the repo.59- A boolean named as a noun (`active` instead of `isActive`).60- The same concept called three different things in three files.61- A magic number or string literal with no name and no comment explaining it.62- A name you struggled to choose (Ousterhout: Hard to Pick Name — investigate63 the design before you commit to any name).64- A `Vague Name` (Ousterhout): too imprecise to convey useful information65 (`handle`, `process`, `do`).6667## The procedure6869For each new identifier:701. Ask: "Could a stranger reading only this name — no body, no context — guess71 what it is and does?" If not, rename.722. Check for noise words and abbreviations; eliminate both.733. Check that the same concept is named consistently elsewhere in the codebase.7475For each comment:761. Ask: "Does this add information the code doesn't already carry?" If no,77 delete it.782. If the *what* is unclear, fix the name. Don't add a comment to compensate.793. If the comment is a `# TODO` or `# hack`, either fix it now or convert it80 to a tracked ticket and link the ticket number.8182When a name is hard to pick: stop naming and investigate the abstraction. A83module with one clear responsibility names itself; one that does two things84can't be named without an `And`.8586## Before / after8788```python89# BEFORE — vague name, comment restates the code90def proc(d):91 # loop through data92 for item in d:93 if item["ts"] < time.time() - 1800:94 del_item(item)9596# AFTER — intention-revealing name, comment carries WHY97# 30-minute threshold per §AUTH-112: tokens issued before this window98# cannot be rotated without a full re-auth, so we purge them proactively99# rather than let them accumulate and slow the next gc sweep.100SESSION_EXPIRY_SECS = 30 * 60101102def expire_stale_sessions(sessions: list[Session]) -> None:103 cutoff = time.time() - SESSION_EXPIRY_SECS104 for session in sessions:105 if session.issued_at < cutoff:106 session_store.delete(session)107```108109Changes: `proc` → `expire_stale_sessions` (verb + domain noun); `d` →110`sessions` (type-and-domain); `item` → `session`; `1800` → `SESSION_EXPIRY_SECS`111(named constant); comment deleted (restated the loop) and replaced with one that112explains the *why* — the requirement reference and the gc motivation.113114## Critique mode115116For each identifier: state whether a stranger could infer its purpose from the117name alone. For each comment: state whether it adds information the code doesn't118carry. Recommend rename or delete as appropriate. Tag findings:119120`[naming-and-comments · vague-name · SEV]`121`[naming-and-comments · comment-repeats-code · SEV]`122`[naming-and-comments · hard-to-pick-name · SEV]`123124`hard-to-pick-name` findings should also trigger a design investigation —125recommend the caller open a `right-sized-design` review on the surrounding126abstraction.127128## References129130- Vague Name, Hard to Pick Name, Comment Repeats Code, Nonobvious Code:131 `../../references/PRINCIPLES.md` §B (Ousterhout red flags table)132- Rule 9 ("Names carry intent; comments carry *why*"): `../../RULES.md`133- Workspace house rule: "the diff is the comment" — `../../RULES.md` Definition134 of Done135- Right-sizing abstractions that produce hard-to-name modules:136 `../right-sized-design/SKILL.md`