Code Comments
Filosofia e regras de comentários cross-language: WHY-not-WHAT por default; comentário só quando o motivo é não-óbvio; doc comments per-lang com formato canônico; TODO/FIXME/HACK com handle + ticket; commented-out code proibido; license header quando aplicável; module docstring quando obrigatório. Anti-patterns enumerados.
Spec — Code Comments
Facet *ode*do Koder Design.
Codifica formalmente a regra global do CLAUDE.md ("default to no comments") como spec auditável + estende com formato per-lang, doc styles, TODO conventions e anti-patterns.
Filosofia: WHYnotWHAT
*efault* não escrever comentário. Identificadores bem nomeados (per code/naming.kmd) + funções curtas (per code/functions.kmd) *ão*a documentação primária do que o código faz.
*screver comentário só quando*
- Esconde
se um *HY*nãoóbvio (constraint de negócio, invariantesutil, workaround por bug específico, comportamento que surpreende)
- O comportamento depende de algo *ora do arquivo*(spec externa,
protocolo de terceiros, RFC, ticket de incidente)
- A escolha entre alternativas igualmente válidas precisa de
justificativa pra evitar refactor inútil futuro
*ão escrever comentário quando*
- Apenas repete o nome do identificador (
# increment counteremcima de
counter += 1) - Descreve o WHAT que já é óbvio do código
- Referencia o "task atual""este fix""caller X" — isso pertence
à PR description, não ao código (commit message + git blame preservam a referência sem rotação)
- Marca código removido (
# was: foo()) — git history tem isso
Exemplos
# ❌ Comenta o WHAT óbvio
# increment retry counter
retries += 1
# ✅ Comenta o WHY não-óbvio
# OAuth2 server occasionally returns 502 mid-handshake (vendor bug
# tracked in #4471); retry up to MAX_RETRIES with backoff before
# surfacing failure
retries += 1
# ❌ Referencia task atual (rotaciona)
# Added for the new login flow PR-#1234
def authenticate(token)
# ✅ Pertence ao PR/commit, não ao código
def authenticate(token)Estilo léxico per-language
| Linguagem | Single-line | Multi-line | Doc comment |
|---|---|---|---|
| Koda | # |
(não tem; usar # consecutivos) |
#: em linhas consecutivas (3+) |
| Go | // |
(não tem; usar // consecutivos) |
// PascalName ... antes de export |
| Dart | // |
|
/// ou /** */ (dartdoc) |
| Python | # |
(não tem) | """...""" triple-quoted (PEP 257) |
| Rust | // |
|
/// ou //! (módulo) |
| JS/TS | // |
|
/** */ (JSDoc/TSDoc) |
| Shell | # |
(não tem) | n/a |
| SQL | -- |
|
n/a |
*rincípio* usar o formato *diomático*da linguagem; não forçar uniformidade total que viola o uso esperado pelo IDE/linter.
Doc comments
R1 — Quando obrigatório
- *oda funçãométodoclasse pública*(exportada do módulo)
- *oda constant pública não-trivial*(não óbvia pelo nome)
- *odo módulo/package*(docstring no topo)
R2 — Quando opcional
- Funções privadas curtas (≤10 linhas) com nome auto-explicativo
- Test functions (nome
test_ouit_should_é a doc)
R3 — Formato
Mínimo: * linha de resumo* Quando relevante: * linha em branco + detalhes*(parâmetros, retorno, raises, exemplos).
def hash_password(password: str) -> str:
"""Hash a password with Argon2id."""def hash_password(password: str, *, time_cost: int = 3) -> str:
"""Hash a password with Argon2id.
Time cost defaults to 3 (OWASP 2024 recommendation). Use higher
values for high-security contexts; benchmark target: ~50ms on
modern CPU.
Args:
password: Plaintext password (max 72 bytes effective).
time_cost: Argon2 t parameter; 3 ≤ t ≤ 10.
Returns:
PHC-format hash string (`$argon2id$v=19$...`).
Raises:
ValueError: If password is empty or time_cost out of range.
"""R4 — Koda specific (#: triple-line)
Ver code/languages/koda-style.kmd § Doc comments. Resumo:
#: Compute SHA-256 hash of a string.
#:
#: Returns 64-char lowercase hex. Raises EncodingError on
#: invalid UTF-8.
def sha256(s)
...
endTODO / FIXME / HACK / XXX / NOTE / WARN
R5 — Formato canônico
# TODO(@handle, ticket): description
# FIXME(@handle, ticket): description
# HACK(@handle, ticket): description — explanation of why
# XXX(@handle): something dangerous; needs careful review
# NOTE: something readers should know but isn't actionable
# WARN: behavior that surprises; non-obvious side effectR6 — Quando usar cada um
| Marker | Significado |
|---|---|
TODO |
Trabalho planejado, não-urgente; tem ticket |
FIXME |
Bug conhecido; *eve*ter ticket |
HACK |
Workaround consciente; explicar o porquê + ticket de remoção |
XXX |
Algo perigoso/duvidoso que merece revisão |
NOTE |
Informação útil pro leitor, não-actionable |
WARN |
Comportamento surpreendente; alerta defensivo |
R7 — Regras
- TODOFIXMEHACK *evem*ter
(@handle, ticket)— autor + ticketde tracking
- Linter falha se TODO/FIXME sem ticket após 30 dias
- HACK exige *xplicação do porquê*após
:(não pode ser só# HACK: fix later) XXXnão exige ticket mas exige revisão code-review- Markers em *nglês*(mesmo em comentário pt-BR raro — markers
são vocabulário fechado universal)
R8 — Heisenbug workarounds
Caso especial: diagnóstico que "acidentalmente conserta" um bug pode ser shipado como workaround permanente, *as exige*
- Comentário explícito explicando que é workaround
- Ticket de follow
up pra rootcause investigation - Marker
HACKouXXX
(Padrão registrado em memory feedback_heisenbug_workaround_pattern.)
Commented-out code
*roibido* Delete + git history. Linter falha se ≥5 linhas consecutivas comentadas com sintaxe que casa com a linguagem.
# ❌
def foo():
bar()
# baz()
# qux()
# frob()
return bar.result()
# ✅
def foo():
bar()
return bar.result()
# git blame mostra o que foi removidoExceção rara: bloco de exemplo/template em README ou doc comment (aceito porque o # está dentro de docstring/markdown).
Section headers
Quando arquivo tem ≥200 linhas e seções lógicas distintas, usar section headers:
# ============================================================
# Public API
# ============================================================
def authenticate(...): ...
def logout(...): ...
# ============================================================
# Internal helpers
# ============================================================
def _hash(...): ...Não obrigatório; não adicionar em arquivos curtos onde o file outline do IDE já dá a estrutura.
License header
R9 — Política Koder
Default: *ão exigir*license header em todo arquivo. Razões:
- LICENSE no root do repo é canônica
- Header em todo arquivo polui git diff e onboarding
- Tooling moderno (SBOM, REUSE) lê do
LICENSEdireto
*xceção* arquivos publicados como SDK público pra terceiros (em `engines/sdk