Documentation Practice

Code Comments: When and How to Write Them

What code comments should explain, what they should not repeat, and practical habits for keeping comments accurate as the code around them changes.

On this page
  1. What a comment is for
  2. Comments that earn their place
  3. Comments that do not
  4. Let the code speak first
  5. Writing style
  6. Keeping comments accurate
  7. A quick example

What a comment is for

Code already says what it does, to a reader who knows the language. What it often cannot say is why it does it that way: the reason for a surprising choice, the constraint it works around, or the assumption it depends on. A good comment fills that gap. A poor comment restates the line beneath it in different words, and adds reading time without adding knowledge.

A useful test is to ask what a competent colleague would wonder when reading this section. If the answer is “why is it done like this?”, a comment is justified. If the answer is “what does this line do?”, the better fix is usually to improve the code itself.

Comments that earn their place

Some kinds of comment are consistently worth writing.

  • Intent and reasoning. For example, a note that a delay exists because a device needs time to settle after power-up, or that a check is deliberately strict because a downstream part misbehaves on bad input.
  • Constraints and units. A value with no explanation of its units is a common source of mistakes. Stating that a variable holds milliseconds rather than seconds, or that an angle is in radians, prevents errors that no compiler catches. Good unit handling is a habit worth building in general, as the topics of unit conversion and dimensional analysis show.
  • Warnings. A short note that changing an order of operations will break something, or that a function is not safe to call from certain contexts.
  • Non-obvious algorithms or formulas. A brief description of the approach and where the details can be found, so that the reader does not have to reverse-engineer it.
  • Known limitations and open questions. Honest notes about what the code does not handle yet, ideally with enough context to be found and acted upon later.
  • Interface descriptions. For public functions and modules, a short description of purpose, inputs, outputs and failure behaviour, in whatever format your language and team conventionally use.

Comments that do not

Some comments cost more than they give.

  • Echoes of the code. A comment saying “increment the counter” above a line that increments a counter.
  • Commented-out code. Old code left in place “just in case” clutters the file and confuses readers about whether it matters. Version control already remembers the past, so deleting it is safe and the history can be recovered if needed.
  • Change logs inside the file. Lists of who changed what and when are better kept in commit messages, where they stay attached to the actual change.
  • Jokes and venting. Remarks about colleagues, frustration or past failures age badly and do not help the next reader.
  • Apologies for bad code. If a section is confusing enough to need an apology, consider simplifying it or at least explaining what makes it hard.

Let the code speak first

Before writing a comment, ask whether a clearer name or a smaller function would make it unnecessary. A variable called t with a comment saying “timeout in seconds” can often become timeout_seconds with no comment at all. A long block with a header comment may be better as a separate function whose name states the purpose.

This does not mean comments are a last resort. It means that names and structure carry the “what”, so that comments can concentrate on the “why”. Debugging benefits too: when you explain a problem aloud, as in rubber duck debugging, you often discover that the explanation you give is the very comment the code was missing.

Writing style

Comments are read many times and written once, so they reward a little care.

  • Use plain, complete sentences where the point is not trivial.
  • Be specific. “Handle edge cases” tells the reader almost nothing; “Return early when the list is empty, because the average below would divide by zero” tells them a lot.
  • Keep comments close to the code they describe, and keep them short.
  • Describe the situation, not the history. “Workaround for a sensor that reports zero during start-up” is more durable than “Fixed on Tuesday after the problem with the sensor”.
  • Follow your team’s conventions for format, tags and language. Consistency matters more than any particular style.

Flags such as a to-do marker can help, but they decay quickly if no one reads them. If you use them, include enough detail for a stranger to act on the note, and look at them from time to time.

Keeping comments accurate

An outdated comment is worse than no comment, because readers trust it and are misled. Accuracy depends on habit more than on tools.

  • Change the comment with the code. When you edit a block, re-read the nearby comments as part of the same edit.
  • Check during review. Reviewers can ask whether the comments still match the change. Good code review includes reading the explanation as well as the logic, and pull requests are a convenient point for that conversation.
  • Comment sparingly where things change fast. The more detail a comment contains about specifics that may change, such as exact values copied from elsewhere, the more likely it is to drift. Point to the single source of truth instead of repeating it.
  • Delete rather than leave doubtful comments. If you are unsure whether a comment is still true and cannot find out, flag it or remove it rather than leave it as an unreliable guide.
  • Let tests carry some of the load. Where behaviour matters, a test documents it in a form that fails when it becomes wrong, which a comment cannot do.

A quick example

Compare two versions of a comment on the same line. The first, “set delay to 50”, repeats the code. The second, “Wait 50 ms for the supply to stabilise before reading; shorter waits gave noisy readings during testing”, tells the reader why the number is what it is and what happens if it is changed. The second takes a little longer to write and may save a long investigation later. Both are illustrations of the principle rather than recommendations for any particular device.

Commenting is a judgment call, and teams differ in how much they prefer. The common thread is to explain what the code cannot, say it briefly, and keep it true.

The complete guide to documentation practice

Documentation Practice for Engineering Teams
Read the guide

Keep exploring

Guides from other topics

All topics →