Writing Meaningful Comments and Documentation Developers Will Read
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:
- What is this? One paragraph explaining the project
- Prerequisites: Node version, Python version, required API keys
- How to run:
npm install && npm start - 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
- Commented-out code: Delete it. That's what git history is for.
- Outdated comments: Wrong comments are worse than none. If code changes, update or remove the comment.
- Obvious comments:
// constructorabove a constructor adds nothing.
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.