Comments
What deserves a comment, what does not, and what to write instead
Comments
A comment is an admission that the code did not say enough on its own. Sometimes that admission is unavoidable and useful; more often it is a signal that the code itself can be improved.
The First Rule
Before writing a comment, try to make the comment unnecessary.
Renaming a variable, extracting a function, or simplifying a conditional usually removes the need for the comment. Code is the source of truth; comments drift, lie, and rot.
// Comment compensating for unclear code
// Check whether the user is over 18
if (u.a >= 18) { ... }
// Comment removed by clearer code
if (user.isAdult()) { ... }Comments to Avoid
Restating the code
i++; // increment i
for (const u of users) { } // loop over usersAdds no information; doubles the maintenance surface.
Misleading or stale comments
A comment that contradicts the code is worse than no comment. Readers cannot tell which is correct, and they often trust the comment first. Treat comments as code: review them, update them in the same commit as the change they describe, and delete them when they no longer apply.
Commented-out code
Delete it. Version control is the place for old code. A block of commented-out code in the working tree creates uncertainty: is it about to be reinstated? Is it a workaround? No reader can tell.
Changelog-style comments
// 2024-03-15 alice: fixed null pointer
// 2024-04-02 bob: added cacheThis is what git log is for. Inline changelogs become noise within months.
Decorative banners and section markers
// ============================================
// USER METHODS
// ============================================Usually a sign the file should be split. If the file is genuinely cohesive, an outline in the file's docstring is sufficient.
Comments Worth Writing
Why, not what
The code shows what it does; the reader cannot easily reconstruct why it does it that way:
// Merchant requires settlement at the rate captured when the order
// was placed, not the rate at payment time.
const rate = order.placedAtRate;This kind of comment captures intent, business rules, and historical context that no amount of code clarity can express.
Warnings about consequences
// Not thread-safe; callers must hold the queue lock.// O(n²) in the size of `permissions`. Acceptable up to ~10k entries;
// switch to a hash join above that.These comments protect future readers from making invalid assumptions.
Markers for known incomplete work
Use a small, agreed vocabulary so the markers are searchable:
TODO— something to add laterFIXME— known defect, scheduled for repairHACK— deliberate workaround, not the right solutionNOTE— context that surprised the author
Always include enough context to act on:
// TODO(alice, PROJ-1234): replace with the new pricing engine
// once the migration is complete.Naked TODO markers without owner or ticket become permanent.
Non-obvious algorithms or formulas
When the algorithm is widely recognized, a name and a citation are usually enough:
// Boyer–Moore majority vote (O(n) time, O(1) space)When it is not, a brief explanation of the invariant or the source of the formula belongs in the code.
Public API contracts
API documentation deserves prose. Cover what the type system cannot:
- Preconditions on inputs.
- Guarantees about outputs.
- Exceptions or error returns and their meanings.
- Side effects, including I/O and persistence.
- Concurrency and re-entrancy properties.
- Performance characteristics relevant to callers.
This is the one place where verbose comments are the norm rather than the exception.
Style and Hygiene
Write comments at the time of writing
Comments written during implementation capture the design rationale while it is fresh. Comments added retroactively tend to translate the code rather than explain it, because the original "why" has already been forgotten.
Update comments in the same commit as the code
A comment is part of the change it describes. Reviewers should treat an unchanged comment over modified code as a defect.
Review comments in code review
Stale comments, restating comments, and missing comments at API boundaries are all valid review points. Comments are first-class citizens, not garnish.
Match the audience
A comment in an internal helper is read by the team. A comment in a public SDK is read by external developers without context. Calibrate the level of explanation to the reader, not to the author's familiarity with the code.
A Test for Each Comment
Before keeping a comment, ask:
- Would a reader miss anything important if this comment were deleted?
- Could the comment be eliminated by renaming a symbol or extracting a function?
- Will this comment still be accurate six months from now?
If the answer to any of these is "no" or "uncertain," rewrite the code instead.