🎈 A doença da superengenharia
Karpathy: "Eles gostam muito de supercomplicar código e APIs, inchar abstrações, não limpar código morto... implementam uma construção inchada de 1000 linhas quando 100 bastariam." Esse é o vício mais difícil de quebrar.
🎯 Por que LLMs incham código
- • Foram treinados em código "profissional" cheio de boilerplate.
- • Confundem "linhas escritas" com "trabalho feito".
- • Adicionam camadas para "parecerem completos".
- • Não têm noção do custo de manutenção que estão criando.
✗ Versão inflada (típica)
3 classes, 20 linhas, 1 caller.
✓ Versão honesta
2 linhas, mesmo efeito.
Volume ≠ Valor
Mais linhas raramente entrega mais. Geralmente entrega menos.
Complexidade essencial
Vem do problema. Aceite.
Complexidade acidental
Vem do código. Combata.
🚫 Sem features especulativas (YAGNI)
YAGNI = You Aren't Gonna Need It. Não adicione "por via das dúvidas" ou "para o futuro". Quase nada do que é feito assim acaba sendo usado, mas todos pagam o custo.
📊 Estatística que pesa
- ~90% das "configurabilidades preventivas" nunca são usadas.
- 100% delas precisam ser lidas, mantidas e testadas.
- Custo médio: 3x mais código para resolver o mesmo problema.
✓ O que FAZER
- ✓Implementar exatamente o pedido
- ✓Hardcode valores até precisar variar
- ✓Adicionar parâmetros quando aparece o segundo caller
- ✓Mencionar futuro como comentário, não como código
✗ O que NÃO fazer
- ✗Parâmetros opcionais "para flexibilidade"
- ✗Hooks de extensão sem extensão prevista
- ✗"Suporte a múltiplos providers" com 1 provider
- ✗Feature flags para coisas que ainda não existem
💡 Regra prática
Se você consegue justificar uma feature só com "talvez", "no futuro", "caso queiramos" — corta. Quando o "caso" virar real, você adiciona em 5 minutos.
🧩 Abstrações de uso único
Abstrair com 1 caller é ruído. Abstrair com 2 callers é coincidência. Abstrair com 3 callers começa a fazer sentido. É a Rule of Three.
Primeiro uso: inline
Escreva direto. Não envolva em função.
Segundo uso: copia
Copy-paste. Sim, mesmo que pareça "errado". Não abstraia ainda.
Terceiro uso: agora sim
Agora você vê o padrão real. Abstraia com base nos 3 usos reais.
⚠️ Custo da abstração prematura
Abstração feita com 1 caller "achando" o padrão acaba modelando a coisa errada. Quando o segundo uso aparece, ele não cabe — e ou quebra o abstrato, ou cria-se um segundo abstrato pior.
É melhor ter duplicação por 10 minutos do que abstração errada por 10 anos.
⚠️ Erros impossíveis não merecem handler
Não envolver código em try/catch para cenários que não podem acontecer naquele contexto. Defensive coding excessivo esconde bugs reais.
✗ Defensive demais
Esconde bugs reais com fallback silencioso.
✓ Direto
Falha alto e cedo se algo errado chegar.
📋 Quando validação faz sentido
- Boundary externa: input do usuário, API request, leitura de arquivo.
- Interface pública: função exportada que outros times chamam.
- Dado não confiável: deserialização, third-party.
Dentro do seu próprio módulo, com tipos definidos e callers conhecidos? Validação é teatro.
💡 Fail loud, fail fast
É melhor o programa explodir num lugar perto da causa do que retornar valor errado silenciosamente e estourar 5 funções depois.
📏 O teste do sênior
Antes de entregar, perguntar: "Um engenheiro sênior olharia esse código e diria 'isso pode ter metade do tamanho'?" Se a resposta é sim, simplifique.
🎯 Checklist do sênior (use antes de entregar)
- ☐ Existe alguma classe/função com apenas 1 caller? → inline.
- ☐ Tem parâmetro opcional usado em 1 lugar? → remove.
- ☐ Tem try/catch que engole erro silenciosamente? → remove ou loga alto.
- ☐ Tem comentário explicando o "que" em vez do "porquê"? → remove (o código fala).
- ☐ Tem nome longo com prefixo redundante? (`UserUserService`) → renomeia.
- ☐ Loop + map + filter + reduce em sequência? → talvez um único laço explícito.
🔧 Como pedir o teste do sênior no CLAUDE.md
🔁 Quando 200 linhas viram 50
O segundo draft quase sempre é o bom. O primeiro draft é exploração; a reescrita é compressão. Pedir a reescrita explicitamente é mais barato do que aceitar o primeiro draft.
Draft 1: faz funcionar
Foco em correção. Pode ter sobras, repetição, verbosidade.
Draft 2: compressão
"Refaça mantendo o comportamento, mas em metade do tamanho." Surpresa: dá pra fazer.
Draft 3: polish
Nomes, casos de borda, comentários onde for não-óbvio. Pronto pra commit.
✓ Padrões de compressão
- ✓Early returns em vez de if/else aninhados
- ✓Operador ternário em atribuições simples
- ✓Eliminar variáveis temporárias usadas 1 vez
- ✓Funções helper viram inline quando têm 2 linhas
✗ Compressão ruim
- ✗One-liners ilegíveis com 5 operações
- ✗Remover nomes descritivos por curtos demais
- ✗Tirar comentários que explicavam "porquê"
- ✗Compressão que reduz performance significativa
💡 Prompt-mágico
"Releia o código. Se você pudesse reescrever em metade do tamanho mantendo legibilidade, faça. Mostre as duas versões."
📝Resumo do Módulo
Próximo Módulo:
1.3 — 🔪 Mudanças Cirúrgicas