Naming Conventions

code specs/code/naming.kmd

Convenções de naming cross-linguagem da Koder Stack: variables/funcs per idiom da linguagem, classes/types sempre PascalCase, constantes SCREAMING_SNAKE_CASE, files snake_case (códigos) ou kebab-case (.kmd), acronyms tratados como palavra (HttpClient não HTTPClient), booleans com prefixo is_/has_/can_/should_. Cross-language exceptions documentadas.

When this spec applies

Primary triggers

All triggers

Specification body

Spec — Naming Conventions

Facet Code do Koder Design.

Pra naming de binários/CLI ver binaries-and-cli/naming.kmd (k<slug> em CLI, paths /opt/koder/<slug>/, etc.).

Pra naming de produtos/marcas ver naming/brand-score.kmd.

Princípio cross-cutting

Cada linguagem tem o seu idiom nativo que a comunidade respeita — forçar uniformidade total atrapalha quem lê. A Koder respeita o idiom da linguagem para identificadores in-source, MAS uniformiza:

  • Classes/Types: sempre PascalCase
  • Constants: sempre SCREAMING_SNAKE_CASE
  • Files: snake_case pra código, kebab-case pra docs
  • Acronyms: tratados como palavra (HttpClient não HTTPClient)
  • Booleans: prefixo semântico

Tabela cross-linguagem

Categoria Koda Go Dart Python Rust JS/TS SQL Shell
Variável local snake_case camelCase camelCase snake_case snake_case camelCase snake_case snake_case
Variável global/module snake_case PascalCase (export) / camelCase (priv) camelCase snake_case snake_case camelCase snake_case snake_case
Function snake_case PascalCase (export) / camelCase (priv) camelCase snake_case snake_case camelCase n/a snake_case
Class/Type/Struct PascalCase PascalCase PascalCase PascalCase PascalCase PascalCase n/a n/a
Interface/Trait/Protocol PascalCase PascalCase (sufixo er opcional: Reader) PascalCase PascalCase PascalCase PascalCase n/a n/a
Constant SCREAMING_SNAKE_CASE PascalCase (Go idiom override OK) kCamelCase (Dart idiom) ou SCREAMING_SNAKE SCREAMING_SNAKE_CASE SCREAMING_SNAKE_CASE SCREAMING_SNAKE_CASE UPPERCASE SCREAMING_SNAKE_CASE
Enum value PascalCase PascalCase camelCase (Dart idiom) SCREAMING_SNAKE_CASE PascalCase PascalCase n/a n/a
Module/Package snake_case lowercase (sem _) snake_case snake_case snake_case kebab-case (npm) ou camelCase n/a snake_case
File de código snake_case.<ext> snake_case.go snake_case.dart snake_case.py snake_case.rs snake_case.ts ou kebab-case.ts snake_case.sql snake_case.sh
Test file <name>_test.<ext> ou test_<name>.py (idiom da linguagem)
Doc file kebab-case.kmd ou kebab-case.md

Override Go: Go usa case pra controle de visibilidade (PascalCase = exported, camelCase = unexported). A Koder respeita isso — não tenta forçar snake_case que quebraria compilação.

R1 — Acronyms tratados como palavra

❌ Errado ✅ Certo
HTTPClient HttpClient
URLParser UrlParser
IDToken IdToken
XMLDocument XmlDocument
parseJSON parseJson
userID userId
koderID koderId

Vale pra todas as linguagens. Acronym de 2 letras também (Id, não ID).

Exceção rara: nomes oficiais de arquivos/protocolos onde "URL" aparece em string literal ("URL" em config) — a string fica como está; só o identificador segue R1.

R2 — Boolean naming

Booleans (variáveis, retornos, flags) devem ter prefixo semântico:

Prefixo Significado
is_ Estado atual: is_active, is_dirty, is_authenticated
has_ Posse/inclusão: has_children, has_permission
can_ Capacidade: can_edit, can_delete
should_ Decisão/política: should_retry, should_redirect
was_ Estado passado: was_modified, was_seen
will_ Futuro próximo: will_expire, will_redirect

Negação não usa not_ ou no_ — usar a forma positiva e negar no uso: is_active = false em vez de is_inactive = true.

R3 — Naming verbs vs nouns

Tipo Convenção
Function Verb phrase: get_user, compute_total, send_email
Boolean function is_*/has_*/can_*/should_* (mesmo critério de var)
Class/Type Noun: User, OrderSummary, EmailValidator
Interface/Trait Adjective ou -er: Comparable, Reader, Serializable
Constant Noun: MAX_RETRIES, DEFAULT_TIMEOUT_SECONDS
Enum Singular noun: Status (não Statuses); values são noun: Active, Pending

R4 — Tamanho

  • Local var em escopo curto (≤10 linhas): pode ser curto (i, n, err)
  • Local var em escopo longo: nome completo (item_count)
  • Module/global: sempre nome completo
  • Function arg: nome completo, exceto receivers Go (r *Repo), iteradores funcionais (x), ou matemática (a, b)
  • Não abreviar arbitrariamente: usr ❌, user ✅; cfg ❌, config
  • Abreviações canônicas aceitas (lista fechada): id, ip, url, db, api, cli, tui, ui, ux, ai, ml, os, vm, kv, js, ts, http, ssh, tls, dns, oidc, pat, sdk, lhs/rhs

R5 — Plurais

Coleções no plural; itens no singular:

users = []         # lista
for user in users  # item

Mapas: users_by_id, count_by_status, etc. (sufixo _by_<key>).

R6 — Negação dupla proibida

not_disabled = true   # ❌
enabled = true        # ✅

R7 — Filenames

  • Código: snake_case.<ext> em todas as linguagens, exceto onde o ecosistema impõe outra convenção (npm kebab-case aceito; Dart exige snake_case por package convention)
  • Docs (.kmd/.md): kebab-case.kmd
  • Config (.toml/.yaml): snake_case ou kebab-case (consistência por projeto)

R8 — Reserved prefixes/sufixes Koder

Identificadores começando com koder_*, kode_*, k_*, _rt_* (runtime), ou terminados em _kmd são reservados a infra Koder. Não usar pra user code dentro de produtos.

Audit (deterministic)

naming-audit.sh (a criar em ticket follow-up) verifica via tree-sitter:

  1. Class/Type/Struct → PascalCase
  2. Constants → SCREAMING_SNAKE_CASE
  3. Acronyms → tratados como palavra (regex)
  4. Booleans → prefixo semântico
  5. Filenames → snake_case ou kebab-case (per-tipo)
  6. No reserved prefix conflict

Severidade medium: warning não-bloqueante por enquanto (linguagem em si pode forçar idiom). Migrar pra hard quando coverage estiver alta o suficiente.

  • code/indentation.kmd — formatação irmã
  • code/languages/<lang>-style.kmd — overrides per-linguagem
  • binaries-and-cli/naming.kmd — naming de surfaces externas
  • naming/brand-score.kmd — naming de produtos/marcas
  • policies/design-governance.kmd

References