Lesson 15 of 54

Comments and Self-Documenting Code

Why Most Comments Are Code Smells

Here's a controversial statement: most comments are failures.

Not failures of documentation. Failures of code.

When you write a comment explaining what code does, you're admitting the code doesn't explain itself. Instead of fixing the code, you've papered over the problem.

Comments as Compensation

Consider this:

Javascript
// Check if user is eligible for discount
if (user.orders > 10 && user.memberSince < Date.now() - 31536000000 && !user.hadRefund) {
  applyDiscount(order);
}

The comment explains what the code does. But why is the code so hard to read that it needs explanation?

Better:

Javascript
const hasEnoughOrders = user.orders > DISCOUNT_ORDER_THRESHOLD;
const hasBeenMemberLongEnough = user.memberSince < yearsAgo(1);
const hasCleanHistory = !user.hadRefund;

const isEligibleForDiscount = hasEnoughOrders && hasBeenMemberLongEnough && hasCleanHistory;

if (isEligibleForDiscount) {
  applyDiscount(order);
}

No comment needed. The code documents itself through clear names.

The Maintenance Burden

Here's the problem with comments: code changes, comments don't.

You fix a bug. You refactor a function. You change the algorithm. The comment stays exactly as it was.

Javascript
// Increment the counter by 1
counter += 2;

This comment was probably accurate once. Then someone changed the code and didn't update the comment. Now the comment is a lie.

Outdated comments are worse than no comments:

  • They mislead readers
  • They make readers distrust all comments
  • They create cognitive dissonance when the code contradicts the comment

The Comment Test

When you're about to write a comment, ask: "Can I change the code so this comment is unnecessary?"

CommentBetter Code
// Loop through usersThe loop already shows this
// Calculate the totalName the function calculateTotal
// Check if expiredUse isExpired or hasExpired
// Convert to uppercaseThe .toUpperCase() call is already clear
// Initialize variablesObvious from context

Bad Comment Categories

Redundant Comments

Javascript
// Set the user's name to the provided name
user.name = name;

The code says this already. The comment adds nothing.

Noise Comments

Javascript
// Default constructor
constructor() { }

// Getter for id
getId() { return this.id; }

These comments take up space without providing information.

Commented-Out Code

Javascript
// function oldImplementation() {
//   // ...200 lines of dead code...
// }

Delete it. That's what version control is for.

Journal Comments

Javascript
// Modified by John, 2019-03-15: Added null check
// Modified by Sarah, 2019-04-20: Changed comparison
// Modified by Mike, 2019-05-10: Refactored loop

This is what git blame is for. Delete these.

Position Markers

Javascript
//////////////////////////////////
// HELPER FUNCTIONS
//////////////////////////////////

If you need markers to navigate your code, your code is probably too long.

Attribution Comments

Javascript
// Written by John Smith

Version control tracks this. Delete it.

The "Don't Comment Bad Code" Principle

Robert C. Martin puts it simply: "Don't comment bad code—rewrite it."

When you feel the urge to write a comment, it's often a signal that the code is too complex. Instead of explaining the complexity, remove it.

Javascript
// BAD: Comment compensates for unclear code
// Calculate price with discount if customer is preferred and order is above minimum
const price = cust.type === 'P' ? 
  ord.total > min ? ord.total * 0.9 : ord.total : 
  ord.total;

// GOOD: Code speaks for itself
function calculatePrice(customer, order) {
  if (customer.isPreferred && order.exceedsMinimum) {
    return order.total * PREFERRED_DISCOUNT_RATE;
  }
  return order.total;
}

When Comments Are Appropriate

Comments aren't always bad. Good comments exist (we'll cover them in the next lesson). But the bar should be high.

A good comment explains something that the code cannot explain:

  • Why the code exists
  • What trade-off was made
  • What constraint forced this approach
  • What historical context matters

Bad comments explain what the code does. Good code already does that.

Practical Exercise

Go to your codebase. Find 10 comments that explain what the code does (not why). For each one:

  1. Can you rename a variable to eliminate the need?
  2. Can you extract a function with a good name?
  3. Can you simplify the logic?
  4. Can you use a constant with a meaningful name?

You'll find that most of these comments can be eliminated by improving the code.


Key insight: Comments that explain what code does are admissions that the code isn't clear enough. Instead of commenting, improve the code. Names, structure, and simplicity are better documentation than any comment.