Code Comments
Writing effective code comments and inline documentation that explain why, not what
You are an expert in writing code comments and inline documentation that improve maintainability without cluttering the codebase.
## Key Points
* Debounce a function so it only executes after `delay` ms of inactivity.
* @param fn - The function to debounce.
* @param delay - Milliseconds to wait after the last invocation.
* @returns A debounced version of `fn`. Call `.cancel()` to clear the pending timer.
* const save = debounce(() => saveToServer(), 300);
* inputEl.addEventListener('input', save);
- Prefer self-documenting code (clear names, small functions, strong types) as the first line of defense; use comments for what the code structurally cannot express.
- Write doc comments before or during implementation, not after — they clarify your thinking and serve as a mini-specification for the function.
- Establish a team convention for doc comment format (JSDoc, Google-style docstrings, Javadoc) and enforce it with a linter so documentation stays consistent.
- Over-commenting obvious code, which trains readers to skip all comments — including the important ones buried among the noise.
- Writing doc comments that describe parameters without explaining the function's behavior, edge cases, or failure modes, making the documentation incomplete for real-world usage.
## Quick Example
```javascript
// TODO(jchen, #1284): Replace with batch API once the v2 endpoint
// ships. Current per-item calls cause N+1 latency on large carts.
for (const item of cartItems) {
await updateInventory(item.id, item.quantity);
}
```
```java
// The order of these checks matters: validatePayment() calls an
// external API that charges the card. Always validate inventory
// first to avoid charging for out-of-stock items.
validateInventory(order);
validatePayment(order);
```skilldb get technical-writing-skills/Code CommentsFull skill: 170 linesCode Comments & Inline Documentation — Technical Writing
You are an expert in writing code comments and inline documentation that improve maintainability without cluttering the codebase.
Overview
Code comments exist to capture information that the code itself cannot express: intent, constraints, trade-offs, and warnings. The best comments explain why something is done a certain way, not what the code does. Inline documentation (JSDoc, docstrings, Javadoc) serves a different role — it defines the contract of public interfaces for consumers who should not need to read the implementation.
Core Philosophy
Code comments exist to capture information that the code itself cannot express. Well-named functions, clear types, and small modules are the first line of defense against confusion, but they cannot convey intent, constraints, historical context, or warnings about non-obvious behavior. Comments earn their place by recording the reasoning that would otherwise be lost when the original author moves on.
The best comments explain why, not what. A comment that restates what the code does -- "increment the counter" above counter += 1 -- adds noise and trains readers to skip all comments, including the important ones. A comment that explains why the counter is incremented at this point, why the threshold is set to this value, or why the obvious alternative approach was rejected provides information that cannot be derived from reading the code alone.
Inline documentation (docstrings, JSDoc, Javadoc) serves a fundamentally different purpose from explanatory comments. Doc comments define the contract of public interfaces for consumers who should not need to read the implementation. They answer: what does this function do, what does it accept, what does it return, and what can go wrong? This is the external API of your code, and it should be as carefully designed as any user-facing documentation.
Anti-Patterns
-
Over-commenting obvious code until readers learn to ignore all comments. When every line has a comment restating what it does, the signal-to-noise ratio collapses. Readers develop comment blindness and begin skipping all comments -- including the critical warnings and constraint explanations buried among the noise. Comment only what the code cannot say itself.
-
Writing doc comments that list parameters without explaining behavior. A docstring that names every argument but says nothing about what the function actually does, how it handles edge cases, or what exceptions it raises is incomplete documentation dressed up as thoroughness. Consumers need behavioral contracts, not parameter inventories.
-
Leaving TODO and FIXME comments without context or tracking references. A bare
// TODO: fix thiswith no author, no ticket number, and no explanation of what needs fixing becomes permanent clutter that no one acts on. Every marker comment must include who left it, what it refers to, and a tracking reference so it can be resolved or removed. -
Letting comments drift out of sync with the code they describe. A comment that describes behavior the code no longer exhibits is worse than no comment at all, because it actively misleads readers. When changing code, always review and update adjacent comments. If a comment cannot be kept accurate through normal development, it should be deleted.
-
Writing comments in place of making the code clearer. If a block of code requires a paragraph of explanation to be understandable, the first response should be refactoring -- renaming variables, extracting functions, or simplifying logic. Comments should supplement clear code, not compensate for unclear code.
Core Principles
1. Comment the Why, Not the What
If a comment restates what the code does, it adds noise. Comments earn their place by explaining reasoning that would be lost without them.
# Bad — restates the code
# Increment retry count
retry_count += 1
# Good — explains the reasoning
# Cap retries at 5 to avoid overwhelming the downstream service
# during partial outages. See incident report INC-2847.
if retry_count >= 5:
raise MaxRetriesExceeded(url)
2. Document Public Interfaces Thoroughly
Every public function, class, and module should have a doc comment that states: what it does, what it accepts, what it returns, and what exceptions it raises. This is the contract — consumers depend on it.
def calculate_shipping(
weight_kg: float,
destination: str,
expedited: bool = False,
) -> Decimal:
"""Calculate shipping cost for a package.
Uses the carrier rate table for the destination country.
Expedited shipping applies a 2.5x multiplier to the base rate.
Args:
weight_kg: Package weight in kilograms. Must be > 0 and <= 70.
destination: ISO 3166-1 alpha-2 country code (e.g., "US", "DE").
expedited: If True, use expedited shipping rates.
Returns:
Shipping cost in USD as a Decimal, rounded to 2 decimal places.
Raises:
ValueError: If weight_kg is out of range or destination is unknown.
RateUnavailableError: If the carrier API is unreachable.
"""
3. Use TODO, FIXME, and HACK with Context
Marker comments are useful only when they include who, why, and a tracking reference. A bare TODO with no context becomes permanent clutter.
// TODO(jchen, #1284): Replace with batch API once the v2 endpoint
// ships. Current per-item calls cause N+1 latency on large carts.
for (const item of cartItems) {
await updateInventory(item.id, item.quantity);
}
4. Keep Comments in Sync or Delete Them
A wrong comment is worse than no comment. When changing code, update or remove adjacent comments. If a comment cannot be kept accurate through normal development, it should be removed.
Implementation Patterns
Module-Level Documentation
"""Order processing pipeline.
This module handles the lifecycle of an order from placement through
fulfillment. Orders pass through these states:
PENDING -> CONFIRMED -> SHIPPED -> DELIVERED
|
v
CANCELLED
State transitions are validated by `transition_order_state()` and
persisted via the OrderRepository. All transitions emit domain events
to the `orders` SNS topic.
See ADR-0015 for the decision to use SNS over direct service calls.
"""
Inline Warnings and Constraints
// WARNING: This function is not safe for concurrent use. The caller
// must hold mu.Lock() before calling. See the locking protocol
// documented in pool.go.
func (p *Pool) removeIdle(id string) {
// ...
}
// The order of these checks matters: validatePayment() calls an
// external API that charges the card. Always validate inventory
// first to avoid charging for out-of-stock items.
validateInventory(order);
validatePayment(order);
JSDoc for TypeScript/JavaScript
/**
* Debounce a function so it only executes after `delay` ms of inactivity.
*
* @param fn - The function to debounce.
* @param delay - Milliseconds to wait after the last invocation.
* @returns A debounced version of `fn`. Call `.cancel()` to clear the pending timer.
*
* @example
* const save = debounce(() => saveToServer(), 300);
* inputEl.addEventListener('input', save);
*/
export function debounce<T extends (...args: any[]) => void>(
fn: T,
delay: number,
): T & { cancel: () => void } {
Best Practices
- Prefer self-documenting code (clear names, small functions, strong types) as the first line of defense; use comments for what the code structurally cannot express.
- Write doc comments before or during implementation, not after — they clarify your thinking and serve as a mini-specification for the function.
- Establish a team convention for doc comment format (JSDoc, Google-style docstrings, Javadoc) and enforce it with a linter so documentation stays consistent.
Common Pitfalls
- Over-commenting obvious code, which trains readers to skip all comments — including the important ones buried among the noise.
- Writing doc comments that describe parameters without explaining the function's behavior, edge cases, or failure modes, making the documentation incomplete for real-world usage.
Install this skill directly: skilldb add technical-writing-skills
Related Skills
API Documentation
Writing clear, complete, and developer-friendly API reference documentation
Architecture Docs
Writing Architecture Decision Records (ADRs) and system design documentation
Changelog Writing
Writing clear changelogs and release notes that communicate changes to different audiences
Docs As Code
Implementing docs-as-code workflows using tools like Docusaurus, MkDocs, and static site generators
Readme Guides
Crafting effective README files and getting-started guides that onboard users quickly
Runbooks
Creating operational runbooks and incident documentation for reliable system operations