home / skills / third774 / dotfiles / documenting-code-comments

documenting-code-comments skill

/opencode/skills/documenting-code-comments

This skill helps audit, clean up, and improve inline code documentation by enforcing self-documenting code and WHY-focused comments.

npx playbooks add skill third774/dotfiles --skill documenting-code-comments

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
7.0 KB
---
name: documenting-code-comments
description: 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.
---

# Code Comment Guidelines

## Core Philosophy

**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%.

### Writing Style Guidelines

**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**:

<AVOID>
- Corporate buzzwords and marketing speak
- AI-sounding language or excessive enthusiasm
- Overly formal/boring documentation style
- Dramatic hyperbole about revolutionary solutions
- Em dashes (—)
- Emojis
- Sycophancy
</AVOID>

### Hierarchy of Documentation

1. **Make code self-documenting** (naming, structure, types)
2. **Use type systems** to document contracts
3. **Add comments only for WHY**, never for WHAT

---

## Refactoring: Preserve Existing Comments

**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:

### Never Remove

- Comments explaining WHY something exists
- Comments warning about gotchas or edge cases
- Comments referencing external context (tickets, specs, RFCs)
- Comments documenting non-obvious business logic

### Update When Necessary

- If refactoring changes behavior the comment describes, update the comment
- If refactoring makes a workaround obsolete, update or remove with the workaround
- Add to existing comments if refactoring introduces new context

### Only Remove When

- The comment is demonstrably incorrect (doesn't match code behavior)
- The comment documents code you're deleting entirely
- The refactoring eliminates the "why" (e.g., removing a workaround makes its explanation obsolete)

```
// 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
```

---

## When NOT to Write Comments

### Never Comment the Obvious

```
// ❌ 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);
```

### Never Duplicate Type Information

```
// ❌ 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 {}
```

### Never Leave Stale Comments

```
// ❌ BAD: Comment doesn't match code
// Returns user's full name
const getEmail = () => user.email;

// ✅ GOOD: Remove or fix
const getEmail = () => user.email;
```

---

## When TO Write Comments

### 1. Explain WHY, Not WHAT

```
// ✅ 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(), []);
```

### 2. Warn About Gotchas and Edge Cases

```
// ✅ 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);
```

### 3. Reference External Context

```
// ✅ 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);
```

### 4. Document Performance Decisions

```
// ✅ 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]));
```

### 5. Complex Business Logic

```
// ✅ Documents business rule
// Discount applies only to orders >$100 AND first-time customers
if (orderTotal > 100 && customer.orderCount === 0) {
```

---

## Comment Formatting Standards

### Single-line Comments

```
// Sentence case, no period for fragments
// Full sentences get periods.
```

### JSDoc/TSDoc for Public APIs

Only when behavior isn't obvious from signature:

```typescript
/**
Validates email format and checks domain blacklist.
  @throws {ValidationError} If format invalid or domain blacklisted
  @example
    validateEmail('[email protected]'); // OK
    validateEmail('[email protected]'); // throws
*/
function validateEmail(email: string): void {}
```

### TODO Format

```
// ✅ GOOD: Actionable with ticket
// TODO(JIRA-567): Replace with batch API when available Q1 2025

// ❌ BAD: No context
// TODO: fix this later
```

---

## Refactor Before Commenting

| 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)` |

---

## Audit Checklist

When reviewing code comments:

1. **Necessity**: For new code, can it be self-documenting? For existing code, is this comment still accurate? If accurate, keep it.
2. **Accuracy**: Does comment match current code behavior?
3. **Value**: Does it explain WHY, not WHAT?
4. **Freshness**: Is it still relevant?
5. **Actionability**: If TODO, does it have a ticket reference?

---

## Language-Specific Patterns

### TypeScript/JavaScript

- Prefer TypeScript types over JSDoc type annotations
- Use `@deprecated` JSDoc tag for deprecated APIs
- Document thrown errors in JSDoc when not obvious

### Go

- Follow effective Go: first sentence is function name + verb
- Document exported functions, unexported can be brief
- Use `// Deprecated:` comment prefix

### Python

- Use docstrings for modules, classes, functions
- Follow Google or NumPy docstring format consistently
- Type hints reduce need for parameter documentation

Overview

This skill provides practical standards for writing self-documenting code and guidelines for when to add or avoid inline comments. It emphasizes naming, types, and structure first, and reserves comments primarily for explaining intent, edge cases, and external context. Use it when auditing, cleaning up, or improving inline documentation to reduce maintenance overhead and comment drift.

How this skill works

The guidance inspects existing comments for accuracy, relevance, and value, and recommends refactors that make code self-documenting before adding comments. It instructs preserving institutional knowledge during refactors, updating comments when behavior changes, and removing only demonstrably incorrect or obsolete comments. It also defines formats for single-line notes, TODOs, and JSDoc/TSDoc for public APIs.

When to use it

  • When auditing a codebase to remove stale or misleading comments
  • During refactoring to preserve or update important context
  • When writing code that has non-obvious business rules or constraints
  • When documenting workarounds, platform bugs, or external references
  • When deciding whether to add JSDoc/TSDoc for public APIs

Best practices

  • Prefer self-documenting code: clear names, small functions, and types before comments
  • Write comments to explain WHY, not WHAT; skip comments that restate code
  • Preserve comments that capture institutional knowledge or edge-case reasoning
  • Keep TODOs actionable with ticket references and context
  • Use sentence case for single-line comments and JSDoc/TSDoc for public API behavior

Example use cases

  • Refactor a messy function and keep its explanatory comment about a historical workaround
  • Audit a repo to find TODOs without tickets and convert them to actionable tasks
  • Add a comment explaining a non-obvious performance trade-off and its benchmark data
  • Document a browser-specific workaround with a link to the ticket or spec
  • Replace repetitive comments by introducing well-named constants and helper functions

FAQ

When is a comment acceptable even if the code is clear?

When it explains intent, why a decision was made, external constraints, or non-obvious edge cases that tests or types do not capture.

Should I remove comments during refactor?

Only remove comments if they are demonstrably incorrect, document deleted code, or the refactor eliminates the reason for the comment; otherwise preserve or update them.