There was a sleep(500) in our codebase. No comment. A helpful colleague removed it—"unnecessary delay, cleaning up." Deployment broke. Turns out an external API had a race condition; the delay was the workaround.

Three hours of debugging later, we put the sleep back. This time with a comment explaining why. That's what documentation is for—preventing future developers from making expensive mistakes.

Comments Explain Why, Not What

If your comment just repeats what the code says, it's noise:

// ❌ Useless - we can read the code
// Increment i by 1
i++;

// Create a new user
const user = new User();

Good comments explain things code can't express:

// ✅ Explains why
// API is 1-based, our array is 0-based
const apiIndex = localIndex + 1;

// Using custom fetch because the standard library
// doesn't handle 429 rate limits correctly
await customFetch(url);

Business rules, workarounds, non-obvious decisions—these need documentation. The syntax is obvious. The reasoning isn't.

Warning Comments Save Hours

Some code looks wrong but is intentionally that way. Mark it:

// WARNING: Do not remove this delay.
// The external API returns 404 if queried immediately after creation.
// We confirmed this with their support team (ticket #12345).
await sleep(500);

Without this, someone will "clean up" the delay and break production. With it, they understand and leave it alone.

Better Than Comments: Better Names

Before writing a comment, ask: can I just rename things?

// ❌ Needs explanation
// Check if user is admin and file isn't locked
if (u.role === 1 && !doc.l) { ... }

// ✅ Self-documenting
const isAdmin = user.role === 1;
const fileIsEditable = !document.isLocked;

if (isAdmin && fileIsEditable) { ... }

Clear names eliminate the need for most comments. Comment only what names can't express.

READMEs: The Front Door

A repo without a README is a store without a sign. New developers don't know what the project does or how to run it.

At minimum, include:

  1. What is this? One paragraph explaining the project
  2. Prerequisites: Node version, Python version, required API keys
  3. How to run: npm install && npm start
  4. How to test: npm test

Put "Getting Started" at the top. Developers are impatient. They want to clone and run in under 5 minutes.

Docstrings for Public APIs

If you're writing a library or shared utilities, use formal docstrings:

/**
 * Calculates total price including tax.
 * 
 * @param {number} subtotal - Price before tax
 * @param {number} taxRate - Tax rate as decimal (0.2 for 20%)
 * @returns {number} Final total
 * @throws {Error} If subtotal is negative
 */
function calculateTotal(subtotal, taxRate) {
    if (subtotal < 0) throw new Error("Negative price");
    return subtotal * (1 + taxRate);
}

IDEs read these and show them in tooltips. Documentation appears exactly when developers need it.

What Not to Do

The Real Test

Documentation is empathy. You're writing for someone debugging your code at 5pm on a Friday. That someone is often future you.

Ask: if I read this in six months, will I understand why it's this way? If not, write it down now while you still remember.

← Back to Debugging & Code Quality

Back to Home