Skip to content
Back to skills

Functional Writing Useful Comments

ASecurity

Use when writing or reviewing comments and documentation, when a comment restates the code, or when a contract cannot be expressed in a type.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 21, 2026
ai-agentsrustgoexpressdocumentation

Works with

  • cli

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 21, 2026

npx -y skills add yutna/functional-design-skills --skill functional-writing-useful-comments --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Functional Writing Useful Comments?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Functional Writing Useful Comments
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yutna-functional-writing-useful-comments/badge)](https://www.skillsdirectory.com/skills/yutna-functional-writing-useful-comments)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: functional-writing-useful-comments
description: Use when writing or reviewing comments and documentation, when a comment restates the code, or when a contract cannot be expressed in a type.
license: MIT
metadata:
  pack: functional-design-skills
  version: 3.3.0
---

# Writing Useful Comments

**In this pack:** [how much design a task warrants](../functional-design/references/calibration.md),
[the notation](../functional-design/references/notation.md), and
[syntax per language](../functional-design/SKILL.md#language-packs).

## Overview

Comments exist to record what the code cannot say. Types state structure;
names state meaning; neither states why a threshold is thirty days, which
other module depends on this ordering, or what the caller must guarantee.
Those facts exist in the author's head and are lost unless written down.

The usual objections to comments are all objections to bad comments.
Comments that restate the code are worthless and go stale; comments that
carry information not present in the code are the difference between a
module a stranger can use and one only its author can.

## When to use

- Writing an exported function, type, or module
- A design decision was not obvious and has a reason
- Something in the code would surprise a reader
- Reviewing a diff whose comments repeat the code
- Designing an interface, where comments come before the code

Not for: naming, which is
[functional-choosing-precise-names](../functional-choosing-precise-names/SKILL.md).

## The rule

A comment must contain information that is not in the code. Test any
comment by deleting it and asking what was lost. If nothing, it should
not exist.

```text
-- worthless: the code says this
-- increment the counter
counter = counter + 1

-- valuable: the code cannot say this
-- Thirty days, not the contractual sixty, because the payment
-- provider expires authorisations at thirty and a longer window
-- produces charges that always fail.
authorisationWindow = Days 30
```

## The four excuses

Every argument for not writing comments is one of these, and each has an
answer.

| Excuse                     | Answer                                        |
| -------------------------- | --------------------------------------------- |
| Good code documents itself | Code says what, never why                     |
| I have no time             | Minutes now against every reader's hours      |
| Comments go out of date    | Only if the code they describe changes unseen |
| The ones I see are useless | They were; write the kinds below              |

The first excuse is the important one: a signature states structure, and
a name states meaning, but neither can state why a threshold is thirty
days, what a caller must guarantee, or which alternative was rejected and
why. Those facts exist only in the author's head. For new code, rule 1 below
says when to write them.

The second is worth examining honestly. Comments written first save time
in the same session, because they expose a bad interface before it is
implemented. See [comments-first.md](references/comments-first.md).

## The kinds worth writing

**Interface comments** describe what a caller must know and the signature
cannot say. Their contents, in order, are listed in
[comment-kinds.md](references/comment-kinds.md). Write these for
everything exported. They belong above the signature and must not
describe the implementation, or callers will depend on it.

**Implementation comments** explain what is not obvious inside: why an
algorithm was chosen, what an unusual step is for, which invariant the
following lines maintain.

**Cross-module comments** record a dependency that neither module's code
shows: "the batch job assumes these rows are ordered by created_at",
"this tag string is the wire contract with the mobile client". These are
the hardest to place; put them where a change would break the assumption.
If two places can break it, comment both and name the other place in each,
so that the comment can be found when the other place changes.

**Rationale comments** record why a choice was made and what was
rejected. They are what stop a future reader "simplifying" a deliberate
decision.

**Data comments** explain a field whose meaning or unit is not obvious.
Where a type can say it, use the type.

**Module comments** sit at the top of a module and say what knowledge it
owns, what it deliberately does not own, and how to use it if the entry
point is not obvious.

See [comment-kinds.md](references/comment-kinds.md).

## Core rules

1. Default. **Write the interface comment before the code.** If it will not fit
   in one short paragraph, the interface is wrong, and you have learned that
   before implementing it. This is for a new module or an exported function; a
   change inside an existing function owes no new interface comment. See
   [comments-first.md](references/comments-first.md).
2. Rule. **Describe things the reader cannot see.** Never restate the signature.
3. Default. **Inside a body, say why, not what.** The what is in the code; the
   why is not. At an interface, say what the signature cannot: requirements,
   failures, what it does not do. An unusual step is the one place a body says
   what: what the step is for, where the line cannot show it.
4. Rule. **Keep interface comments free of implementation.** Anything a caller
   should not rely on must not be in the interface comment.
5. Default. **Put the comment where the reader will be.** Next to the code it
   explains, not in a document elsewhere. A convention that holds across the
   codebase has no one place in the code, and goes in the project's instructions
   file. A dependency between two places is commented at both, each naming the
   other.
6. Rule. **Update comments in the same edit.** A false comment costs more than
   no comment.
7. Default. **Prefer a type to a comment.** If the comment states a constraint,
   a type can often state it instead, and then it cannot go stale. The comment
   stays where no type can say it: why a choice was made, and a constraint that
   depends on the time, on another system or on a record stored somewhere else.
   See
   [functional-constraining-primitive-values](../functional-constraining-primitive-values/SKILL.md).

## What belongs in an interface comment

For an exported function, with the contents in the order
[comment-kinds.md](references/comment-kinds.md) gives:

```text
-- The total is a whole number of satang: the sum of each treatment's
-- catalogue price times its quantity.
--
-- Requires: every treatment code in the booking exists in the
-- catalogue; callers get that guarantee from validateBooking.
-- Fails with: PriceUnavailable when the catalogue has no price today;
-- TotalTooLarge above the ten-million limit set by the finance team.
-- Does not: apply discounts, which happen later in the pipeline.
priceBooking :
  Catalogue -> ValidatedBooking -> Result<PricedBooking, PricingError>
```

The "does not" line is often the most valuable, because it answers the
question a reader is actually asking.

## Red flags

- A comment that restates the line below it
- A comment that describes how, in an interface comment
- A comment contradicted by the code
- A commented-out block left in place
- An exported function with no comment and a non-obvious contract
- A comment saying "temporary" or "for now" older than a month
- A constant with no explanation of where its value came from

## Common mistakes

- **Documenting the obvious and skipping the subtle.** The getter has
  three lines of documentation and the concurrency assumption has none.
- **Explaining what a good name would say.** Fix the name instead.
- **Writing comments last.** By then the design is fixed and the comment
  is a transcription.
- **Duplicating a comment at every call site.** Put it once, at the
  definition. A cross-module comment is the exception, and it names the
  other place.
- **Using comments to apologise.** "This is ugly but works" tells the
  reader nothing they cannot see. Say what would be better and why it was
  not done. See
  [working-in-existing-code.md](../functional-programming-strategically/references/working-in-existing-code.md).
- **Leaving a stale comment because the change was small.** Staleness is
  what destroys trust in every other comment.

## Related skills

- [functional-choosing-precise-names](../functional-choosing-precise-names/SKILL.md)
- [functional-deciding-what-matters](../functional-deciding-what-matters/SKILL.md)
- [functional-designing-deep-modules](../functional-designing-deep-modules/SKILL.md)
- [functional-hiding-information](../functional-hiding-information/SKILL.md)

## Further reading

- [comment-kinds.md](references/comment-kinds.md) gives the shape of each
  kind, with examples and placement rules.
- [comments-first.md](references/comments-first.md) explains using the
  interface comment as a design tool before implementing.

Files in this skill

  • SKILL.md8.7 KB
  • references/comment-kinds.md4.9 KB
  • references/comments-first.md3.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.