# Key functions and complex logic have inline comments or JSDoc

- **Pattern:** `ab-000673` (`code-maintainability.documentation.function-comments`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000673
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000673)

## Why it matters

Undocumented complex logic — scoring algorithms, multi-step data transformations, non-obvious conditionals — forces every developer who touches that code to reverse-engineer it from the implementation. ISO 25010 maintainability.analysability and reusability both degrade: exported functions without JSDoc cannot be safely consumed by callers who don't understand the contract. AI-generated business logic is especially prone to undocumented complexity because the model writes correct-but-opaque implementations that prioritize functionality over legibility.

## Severity rationale

Medium because undocumented complex logic multiplies the time required to safely modify or reuse it, but the immediate runtime behavior is unaffected.

## Remediation

Focus documentation effort on the code that earns it: non-trivial business logic, complex conditionals, and exported utility functions. Explain the *why*, not just the *what*:

```ts
/**
 * Computes the weighted category score for audit telemetry.
 * Skip/error results are excluded from both numerator and denominator
 * so they don't penalize the score as if they failed.
 */
export function computeCategoryScore(checks: Check[]): number | null {
  const applicable = checks.filter(c => c.result === 'pass' || c.result === 'fail')
  if (applicable.length === 0) return null
  // ...
}
```

TypeScript language servers surface JSDoc in IDE tooltips — document exported functions with `@param` and `@returns` and callers get inline help without reading the source.

## Detection

- **ID:** `function-comments`
- **Severity:** `medium`
- **What to look for:** Examine the 10-15 most substantial non-trivial functions or methods in the codebase (focus on business logic, data transformations, algorithm-like code, and complex conditionals — not simple getters or straightforward CRUD). Check for:
  - JSDoc comments (`/** ... */`) on exported functions explaining parameters and return values
  - Inline comments explaining why (not just what) non-obvious logic does
  - Complex conditionals explained with a comment

  Do not penalize simple, self-explanatory functions for lacking comments. The question is whether the genuinely complex parts have any documentation.
- **Pass criteria:** Count all non-trivial functions (over 10 lines of logic, or containing complex conditionals/algorithms) and classify each as documented or undocumented. At least 60% of non-trivial functions have at least a brief comment explaining their purpose or non-obvious behavior. Report the ratio: "X of Y non-trivial functions are documented."
- **Fail criteria:** The majority of complex functions (over 5 lines of non-trivial logic) have no comments whatsoever. Or the codebase has complex business logic (scoring, calculations, multi-step processes) with zero documentation.
- **Skip (N/A) when:** The project has no non-trivial logic — only simple CRUD operations and UI rendering with no complex transformations. Signal: all functions are <5 lines and have self-explanatory names.
- **Detail on fail:** `"Complex business logic in lib/scoring.ts has no comments — 80-line scoring function with multiple weighted calculations and edge cases is undocumented."` or `"10 exported utility functions in lib/ have no JSDoc — parameter types and return values must be inferred from TypeScript types alone."`
- **Remediation:** Documentation doesn't need to be exhaustive. A one-line comment on a complex function pays dividends for years. Focus on explaining the why, not just the what:

  ```ts
  /**
   * Computes the weighted category score for audit telemetry.
   * Skip/error results are excluded from both numerator and denominator
   * so they don't penalize the score as if they failed.
   */
  export function computeCategoryScore(checks: Check[]): number | null {
    const applicable = checks.filter(c => c.result === 'pass' || c.result === 'fail')
    if (applicable.length === 0) return null
    // ...
  }
  ```

  For exported functions, add JSDoc with `@param` and `@returns` — TypeScript language servers will surface this in IDE tooltips, helping future developers without them having to read the source.

## External references

- iso-25010 maintainability.analysability
- iso-25010 maintainability.reusability

Taxons: code-quality

HTML version: https://auditbuffet.com/patterns/ab-000673
