Code Readability and Maintainability
If the code already makes something obvious, a comment that repeats it is not doing useful work.
A Function Buried in Comments
Comments are written to help a reader understand code, but a comment can also get in the way. Imagine opening a function and finding a comment on nearly every line. Each comment is technically correct, yet the function is harder to read than it should be. This article follows one example from start to finish: first you will read a heavily commented function and count what it actually tells you, then you will rewrite the comments so they carry real information, and finally you will practice the test that decides whether a comment belongs in the code at all.
What do you think happens?
Before reading the code below, predict: if every line has a comment that restates the line, how much new understanding does the reader gain from the comments?
Reveal answer
Almost none, because the comments only repeat what the code already says
The source describes this exact situation: when each line carries a comment that simply restates it, the reader has twice as much text to read and gains no new understanding. The comment becomes noise, and noise makes the important parts of the function harder to find.
Tracing What the Reader Learns
Here is a generated illustration of an over-commented loop. Read it once as a reader scanning the function would, and notice which facts you already get from the code alone.
Trace the reader's experience line by line. The comment above the if statement says the code checks whether the status is cancelled. The if statement already says that. The comment beside continue says the loop skips to the next order, which the continue keyword already states. The comment above ship says the order is sent to the warehouse, which is what the call ship(order) already shows. Three comments, and not one of them tells the reader anything the code did not already make obvious.
Two Guidelines for Commenting Code
The guidance behind this topic comes down to two short rules. The first is negative: do not say in comments what can be clearly stated in code. If the code already makes something obvious, a comment that repeats it is not doing useful work. The second is positive: state intent in comments. The code shows what happens, and a good comment tells the reader what the code is trying to accomplish or why it is written that way.
Intent, in the context of a comment, is the purpose or reason behind a piece of code. It answers questions like why this check exists or why this step happens at this point, rather than what the next line does mechanically.
Intent is usually the information that is hardest to recover from code alone. Code records what a program does, but it rarely records the reason a decision was made. A reader can see that a status is compared to cancelled; they cannot see from the code that a business rule is behind it. That missing reason is exactly what a good comment supplies.
Comments that describe the mechanics of a line should usually be rewritten or removed. Comments that carry purpose should be kept.
Rewriting a Comment to State Intent
Now take the same function and keep the code exactly as it was. Only the comments change. The rewrite below replaces the mechanical comments with comments that explain purpose. The two versions do the same thing; the difference lies only in the comment text.
for order in orders:
# check if the order status is cancelled
if order.status == 'cancelled':
# skip to the next order
continue
# send the order to the warehouse
ship(order)Each comment restates the line beneath it.
for order in orders:
# Cancelled orders must never reach the warehouse, so they are dropped here
if order.status == 'cancelled':
continue
# Shipping happens last so that only orders passing the status check are sent
ship(order)Each comment explains why the line exists.
Compare the two. The rewritten comment above the if statement no longer repeats the comparison. It states the rule the comparison enforces, which the reader could not infer from the status check alone. The comment beside continue was dropped, because the keyword already says what happens. The comment above ship now explains the ordering, which is information the code does not carry. The rewrite is shorter, and every remaining word helps.
for order in orders:
if order.status == 'cancelled':
continue
ship(order)- 1Each order is taken from the list in turn.
- 2The status check decides whether the order is eligible for shipping.
- 3Skipped orders never reach ship, and the loop moves on to the next order.
- The loop visits each order once.
- The if statement tests the status; no comment is needed to explain the comparison itself.
- The continue keyword skips the rest of this iteration; its meaning is already clear from the code.
The Deletion Test for Comments
A practical way to judge any comment is to imagine deleting it and asking what a reader would still not know. If the answer is nothing, the comment is restating the code and can be removed. If the answer is a reason, a purpose, or a constraint, the comment is carrying information the code cannot give on its own and should be kept or rewritten to say that more clearly.
The flowchart turns the deletion test into a sequence of questions. Start by asking whether the comment repeats what the code states. If it does, the comment adds noise and should go. If it does not, ask whether a reader would lose understanding without it. When the answer is yes, check whether the wording describes purpose; if it only describes mechanics, rewrite it around intent.
Mistakes Readers Make With Comments
Common mistake Commenting every line by default
What it looks like# add one to count above count += 1Why it failsThe reader now has twice as much text to read and gains no new understanding. The important parts of the function become harder to find.
Do this insteadComment only where the code does not already make the point obvious, and where a reader would otherwise be missing a reason.
Common mistake Keeping a comment because it was written with effort
Why it failsThe effort of writing a comment does not make it useful. The deletion test asks what a reader would still not know, not how much work went into the text.
Do this insteadApply the deletion test to every comment, and remove those that only restate the code.
Common mistake Describing mechanics where intent was needed
What it looks like# skip to the next orderWhy it failsThis tells the reader what continue does, which the keyword already shows. It omits why the order is skipped.
Do this insteadRewrite the comment to state the rule behind the skip, so the reader learns the purpose.
Judging Comments in Your Own Code
Look at this line: x = x * 2 # multiply x by two. Apply the deletion test. Does the comment tell a reader anything the code does not? If not, rewrite it so that it states why x is doubled, or explain why you would delete it instead.
Hints
- Ask first whether the comment repeats the assignment in words.
- A useful comment would name the reason, such as a unit conversion or a business rule, if one applies in the code's context.
Take a function you wrote recently. For each comment, write down what a reader would still not know if the comment were deleted. Delete the comments where the answer is nothing, and rewrite the rest so each states intent.
Hints
- Be honest about comments that only describe what the next line does.
- Look especially for places where a decision was made for a reason the code does not record.
Key Takeaways
- Do not say in comments what can be clearly stated in code; a comment that restates a line adds noise and no understanding.
- State intent in comments: explain the purpose or reason behind code, which the code alone often does not reveal.
- Apply the deletion test: imagine removing a comment and ask what a reader would still not know.
- Rewrite comments that only describe mechanics, and keep the ones that carry purpose.