Standards for writing self-documenting code and best practices for when to write (and avoid) code comments. Use when auditing, cleaning up, or improving inline code documentation.
The best comment is the one you didn't need to write.
Self-documenting code reduces maintenance burden and prevents comment drift. Studies show clear naming and structure can reduce onboarding time by up to 30%.
Tone: Be direct, practical, and clear. Write in a natural and relaxed tone. Be approachable and down-to-earth with some personality, but light on the slang and excessive casual terms.
Avoid:
This skill's guidance applies to writing new code. When refactoring existing code, preserve comments.
Existing comments represent institutional knowledge. Someone wrote them for a reason. During refactoring:
// BAD: Stripping context during refactoring
// Before: // Retry 3x - payment gateway has transient failures (JIRA-892)
// After: (comment removed, code unchanged)
// GOOD: Preserving context during refactoring
// Before: // Retry 3x - payment gateway has transient failures (JIRA-892)
// After: // Retry 3x - payment gateway has transient failures (JIRA-892)
// GOOD: Updating comment when refactoring changes behavior
// Before: // Retry 3x - payment gateway has transient failures
// After: // Retry with exponential backoff - payment gateway has transient failures
// โ BAD: Restates code
const name = user.name; // Get the user's name
items.forEach(item => process(item)); // Loop through items
// โ
GOOD: Self-documenting
const userName = user.name;
items.forEach(processItem);
// โ BAD: Types already document this
/** @param {string} email - The email string to validate */
function validateEmail(email: string): boolean {}
// โ
GOOD: Types speak for themselves
function validateEmail(email: string): boolean {}
// โ BAD: Comment doesn't match code
// Returns user's full name
const getEmail = () => user.email;
// โ
GOOD: Remove or fix
const getEmail = () => user.email;
// โ
Explains reasoning
// Use exponential backoff - service rate-limits after 3 rapid failures
const backoffMs = Math.pow(2, attempts) * 1000;
// โ
Documents constraint
// Must run before useEffect to prevent hydration mismatch
useLayoutEffect(() => initTheme(), []);
// โ
Critical warning
// IMPORTANT: Assumes UTC - local timezone causes date drift
const dayStart = new Date(date.setHours(0, 0, 0, 0));
// โ
Non-obvious behavior
// Returns null for deleted users (not undefined) - check explicitly
const user = await getUser(id);
// โ
Links to ticket
// Workaround for Safari flexbox bug (JIRA-1234)
display: '-webkit-flex';
// โ
References specification
// Per RFC 7231 ยง6.5.4, return 404 for missing resources
return res.status(404);
// โ
Explains optimization with data
// Map for O(1) lookup - benchmarked 3x faster than array.find() at n>100
const userMap = new Map(users.map(u => [u.id, u]));
// โ
Documents business rule
// Discount applies only to orders >$100 AND first-time customers
if (orderTotal > 100 && customer.orderCount === 0) {
// Sentence case, no period for fragments
// Full sentences get periods.
Only when behavior isn't obvious from signature:
/**
Validates email format and checks domain blacklist.
@throws {ValidationError} If format invalid or domain blacklisted
@example
validateEmail('user@example.com'); // OK
validateEmail('spam@blocked.com'); // throws
*/
function validateEmail(email: string): void {}
// โ
GOOD: Actionable with ticket
// TODO(JIRA-567): Replace with batch API when available Q1 2025
// โ BAD: No context
// TODO: fix this later
| Instead of commenting... | Refactor to... |
|---|---|
// Get active users |
const activeUsers = users.filter(u => u.isActive) |
// Check if admin |
const isAdmin = user.role === 'admin' |
// 86400000 ms = 1 day |
const ONE_DAY_MS = 24 * 60 * 60 * 1000 |
// Handle error case |
Extract to handleAuthError(err) function |
// Calculate total with tax |
const totalWithTax = calculateTotalWithTax(items) |
When reviewing code comments:
@deprecated JSDoc tag for deprecated APIs// Deprecated: comment prefix