Code Anti-patterns
Catálogo cross-language de anti-patterns proibidos: eval/dynamic exec sem audit, magic numbers, god classes, deep nesting, mutable global state, singleton sem DI, catching genérico, null propagation, premature optimization, boolean trap. Linter config canônica per linguagem. Code review checklist top-10. Cross-link com APs específicos das per-language style specs.
Spec — Code Anti-patterns
Facet *ode*do Koder Design.
Catálogo cross-language. APs específicos de uma linguagem vivem em
code/languages/<lang>-style.kmd(ex: 5 APs Koda).
Crosslanguage antipatterns
AP-X1 — eval / dynamic exec sem audit
# ❌
result = eval(user_input)
exec(template.format(...))// ❌
new Function(userCode)();
window.eval(snippet);*isco* code injection / RCE / arbitrary code exec. *xceção* tooling de dev (REPL Koda, sandbox Koru) — exige audit explícito + sandbox.
AP-X2 — Magic numbers
# ❌
if user.age >= 18: ...
sleep(86400)
buffer = bytearray(4096)
# ✅
LEGAL_AGE = 18
SECONDS_PER_DAY = 86400
DEFAULT_BUFFER_BYTES = 4096
if user.age >= LEGAL_AGE: ...
sleep(SECONDS_PER_DAY)
buffer = bytearray(DEFAULT_BUFFER_BYTES)*xceções aceitas sem extrair*
0,1,-1em loops/index2em divisão por 2 (binary search)- HTTP status codes (
200,404) — convenção universal
AP-X3 — God class / God function
Coberto em code/functions.kmd AP-F1. Resumo: classe com >500 linhas ou >20 métodos públicos = quebrar por responsabilidade.
AP-X4 — Deep nesting (> 4 níveis)
# ❌
def f():
if a:
for x in xs:
if b:
while c:
if d: # 5 níveis
...Refatorar via:
- Early return / guard clauses (
code/functions.kmdR3) - Extract function pra blocos internos
- Replace conditional com dispatch (dictmatchpolymorphism)
AP-X5 — Mutable global state
# ❌ Global muta entre tests; race condition em concurrent
_cache = {}
def get(k):
return _cache.get(k)
def set(k, v):
_cache[k] = v# ✅ Encapsulated, dependência injetável
class Cache:
def __init__(self):
self._data = {}
def get(self, k): return self._data.get(k)
def set(self, k, v): self._data[k] = v
# main()
cache = Cache()
handler = Handler(cache=cache)*xceções* constantes immutable (PI, config readonly carregada no boot).
AP-X6 — Singleton sem dependency injection
# ❌ Hard-coded singleton; impossível mock em teste
class DatabaseClient:
_instance = None
@classmethod
def get(cls):
if cls._instance is None:
cls._instance = cls(...)
return cls._instance
# Caller
def handler(req):
db = DatabaseClient.get() # hard-coupled
...# ✅ DI
def handler(req, db):
...
# main wires the singleton
db = DatabaseClient(...)
app.add_route("/", lambda req: handler(req, db))AP-X7 — Catching Exception/Error genérico
Coberto em code/error-handling.kmd AP-E1.
APX8 — Null/nil propagation sem nullcheck
# ❌ Pode quebrar em qualquer ponto da chain
result = user.profile.address.city.upper()# ✅ Optional chaining ou validação
city = (user.profile.address.city.upper()
if user and user.profile and user.profile.address
else None)
# OU usar Optional/Maybe pattern
city = (Some(user)
.map(lambda u: u.profile)
.map(lambda p: p.address)
.map(lambda a: a.city.upper())
.unwrap_or(None))Per linguagem:
- TS: optional chaining (
user?.profile?.address?.city?.toUpperCase()) - Rust:
Option<T>+?operator - Dart:
user?.profile?.address?.city?.toUpperCase() - Kotlin: similar
- Koda:
user&.profile&.address&.city&.upcase
AP-X9 — Premature optimization
# ❌ Otimização micro sem profile
# "Trocou map por list comprehension porque é mais rápido (sem medir)"
# "Cacheou resultado em variável (single use, sem ganho)"
# "Usou regex compilada (chamada 1 vez)"
# ✅ Default código clear; otimizar quando profile mostra hot path
result = [transform(x) for x in items]Crosslink com `policies/hyperscalefirst.kmd`: otimização que *ão*pede esforço extra (escolher estrutura O(n log n) em vez de O(n²) quando ambos têm 1 linha) é encorajada — outro lado do default.
AP-X10 — Boolean trap
Coberto em code/functions.kmd AP-F2.
APX11 — Print/log para debug nãoremovido
# ❌ Production code com print de debug
def handler(req):
print(f"DEBUG: req = {req}") # ← esquecido
...Linter detecta print()console.log()fmt.Println() em src/ (allowed em test/ e cmdtool).
APX12 — Commentedout code
Coberto em code/comments.kmd.
APX13 — Copypaste programming sem extract
Mesmo bloco de 5+ linhas duplicado em ≥3 lugares = extract function.
# ❌ Repetido 4 vezes
user = db.query("SELECT * FROM users WHERE id = ?", uid)
if not user:
log.warn("user not found", uid=uid)
metrics.miss("user.lookup")
return None
return User.from_row(user)
# ✅ Extract
def fetch_user(uid):
user = db.query("SELECT * FROM users WHERE id = ?", uid)
if not user:
log.warn("user not found", uid=uid)
metrics.miss("user.lookup")
return None
return User.from_row(user)APX14 — Reinventar wheel sem checar `code/reusefirst.kmd`
Implementar caching, retry, validação, parsing de string canônica (email, URL, IP) sem checar se SDK Koder já tem. Cross-link com policies/reuse-first.kmd 3-question check.
AP-X15 — TODO sem ticket
Coberto em code/comments.kmd R7.
APX16 — Sideeffect import/init não-óbvio
# ❌ Import-time side effect
# foo.py
print("Loading foo") # ← roda na primeira import; surpresa
db.connect() # ← muda global state na import
# ✅ Lazy
def init():
db.connect()AP-X17 — Race condition em concurrent code
Acesso compartilhado sem sync (lockmutexchannel). Per linguagem:
- Go: race detector (
go test -race) - Rust: compiler já bloqueia naturalmente
- Python: GIL não salva — async/await + shared state ainda race-y
- JS: single-threaded mas async pode sequenciar wrong
AP-X18 — Hardcoded credentials/secrets
# ❌ Nunca
API_KEY = "sk_live_abc123..."
DATABASE_URL = "postgres://user:pass@host/db"
# ✅ Env / vault
API_KEY = os.environ["API_KEY"]
DATABASE_URL = vault.get("DATABASE_URL")Linter falha em strings que casam com pattern de secret (key, token, password literal).
Perlanguage antipatterns (cross-reference)
Cada code/languages/<lang>-style.kmd lista APs específicos:
| Lang | APs específicos | Localização |
|---|---|---|
| Koda | AP1 array aliasing, AP2 implicit globals, AP3 string concat loop, AP4 mutate during iter, AP5 runtime research file | code/languages/koda-style.kmd |
| Go | (futuro) zero-value misuse, ignored error, goroutine leak | code/languages/go-style.kmd |
| Rust | (futuro) unwrap em production, unsafe sem Comment Safety | code/languages/rust-style.kmd |
| Python | (futuro) mutable default, late binding em closure | code/languages/python-style.kmd |
| Dart | (futuro) FutureBuilder rebuild loop, BuildContext após async gap | code/languages/dart-style.kmd |
Linter config canônica per linguagem
Templates em meta/docs/stack/specs/code/linter-configs/:
| Linguagem | Config canônica | Arquivo |
|---|---|---|
| Go | golangci-lint |
golangci.template.yml |
| Rust | clippy.toml + cargo deny |
clippy.template.toml |
| Python | ruff (substitui flake8blackisort) |
ruff.template.toml |
| Dart | analysis_options.yaml |
analysis_options.template.yaml |
| JS/TS | eslint flat config |
eslint.config.template.mjs |
| Shell | shellcheck (opções via flag) |
.shellcheckrc.template |
*rincípio* cada projeto novo copia o template canônico; overrides exigem comment explicando por que.
Code review checklist (top-10)
Imprimir/usar em todo PR review:
- ☐ Naming segue
code/naming.kmd(variables, classes, files) - ☐ Funções dentro de lengthcomplexity limits (`codefunctions.kmd`)
- ☐ Errors handled per
code/error-handling.kmd(no swallow, no log+throw) - ☐ Comments seguem WHY
notWHAT (code/comments.kmd); TODO com ticket - ☐ Imports ordenadosgrouped (`codeimports.kmd`)
- ☐ Sem magic numbers (extraídos pra constants)
- ☐ Sem hardcoded secrets / credentials (env/vault)
- ☐ Sem global mutable state novo (DI ou encapsulação)
- ☐ Tests cobrem golden path + edge cases
- ☐ Doc comment em export pública (ModuleClassFunction)
Audit deterministic
anti-patterns-audit.sh agrega:
- Magic numbers detector (allowlist de 01-12HTTP codes)
evalexecFunction/globalThis['eval']detector- Hardcoded secret detector (regex high-entropy + known prefixes)
- Printconsole.log em src sem allowlist
- TODO sem ticket após 30 dias
- Cyclomatic complexity por function (delegate
code/functions.kmd) - Deep nesting > 4 levels
Cross-link
code/comments.kmd— TODO format, commented-out codecode/error-handling.kmd— generic catch, log+throwcode/functions.kmd— length, complexity, boolean trapcode/imports.kmd— wildcard, side effectscode/naming.kmd— magic number = unnamed constantcode/languages/koda-style.kmd— 5 APs Kodapolicies/reuse-first.kmd— não reinventarpolicies/hyperscale-first.kmd— premature opt boundarypolicies/security.kmd— secrets handling