"Isso aqui está estranho" não é um comentário de PR review. É uma sensação que precisa de nome próprio. Em 1999, Kent Beck e Martin Fowler nomearam dezenas dessas sensações para que o time pare de discutir percepção e comece a apontar problema.
Code Smells não são bugs, não são estilo. São padrões de design ruim que aumentam a probabilidade de bugs futuros e dificultam manutenção. Beck e Fowler nomearam dezenas deles para que o time pare de discutir percepção e comece a apontar problema com nome próprio.
Você revisa o PR. Vê uma classe que recebe três objetos e chama getters de todos eles para fazer a operação. Algo te incomoda. Você comenta: "esse método está esquisito, podia estar em outro lugar". O autor responde: "Funciona, passa nos testes; qual o problema?"
Você não consegue articular o problema. Sai da revisão com sensação ruim. Aprova mesmo assim.
O problema tem nome. Isso se chama Feature Envy. E é um dos dezenas de padrões catalogados por Kent Beck e Martin Fowler em Refactoring (1999) para resolver exatamente esse tipo de discussão: dar nome ao que o reviewer experiente sente, mas não consegue explicar.
Para usar a métrica corretamente, é fundamental distinguir três categorias que costumam ser confundidas:
| Categoria | O que é | Exemplo |
|---|---|---|
| Bug | Erro de execução. O código faz algo que não deveria. | if (x != 5) quando o intent era if (x == 5) |
| Code Smell | Padrão de design ruim. Funciona, mas tem alta probabilidade de virar um bug ou de ser doloroso de manter. | Método com 200 linhas; classe que invade outra |
| Estilo | Convenção estética. Não tem impacto técnico real. | Nomear userId ou user_id; chaves em linha nova |
Linters detectam todos os três. A diferença está no nível de gravidade. Code Smell é a categoria do meio — não te quebra hoje, mas te quebra em três meses se você ignorar.
A análise estática moderna divide os Code Smells em duas categorias. A primeira é dos smells estruturais — problemas genéricos de design, independentes de linguagem. Existem mais de 30 tipos fundamentais. Os mais comuns:
A segunda frente: smells idiomáticos — convenções específicas de linguagem. Centenas de regras por linguagem.
Optional em vez de retornar null; preferir composição sobre herançaany; usar readonly quando possívelinterface{} desnecessárioO Feature Envy é o exemplo mais didático porque captura exatamente aquilo que o reviewer experiente sente sem conseguir nomear.
class OrderProcessor {
calculateDiscount(customer, order) {
if (customer.getTier() === 'GOLD' &&
customer.getYearsActive() > 2) {
if (order.getValue() > 1000 &&
order.getItems().length > 5) {
return order.getValue() * 0.15;
}
}
return 0;
}
}
class Order {
private qualifiesForDiscount(customer) {
return customer.isGoldVeteran() &&
this.value > 1000 &&
this.items.length > 5;
}
// Metodo pode ser chamado direto na
// instancia da order, sem expor getters.
calculateDiscount(customer) {
return this.qualifiesForDiscount(customer)
? this.value * 0.15
: 0;
}
}
Olhe a função: ela recebe customer e order, mas não usa nada da própria classe OrderProcessor. Todos os getters são de objetos externos. Isso é "comportamento no lugar errado" — o método tem mais interesse nos dados de order (e secundariamente customer) do que nos seus próprios.
Na versão refatorada, a lógica vive em Order (que conhece seus próprios dados) e usa um método auxiliar de Customer (isGoldVeteran()) que encapsula a regra de elegibilidade. Os getters expostos para fora desaparecem. O código fica mais difícil de quebrar do lado de fora.
A análise estática é excelente para detectar smells estruturais e idiomáticos. Ferramentas modernas de análise estática (ESLint, Prettier, RuboCop, Pylint, Checkstyle e a plataforma SQA da Codurance, que integra todas as cinco métricas da série) detectam Long Method, Feature Envy, parâmetros demais, padrões idiomáticos errados — em segundos, em milhões de linhas de código.
O que análise estática não captura bem:
Análise estática libera tempo dos reviewers — em vez de gastar atenção apontando "esse método está muito longo", eles podem focar em "essa modelagem está errada". Use o linter para o que é mecânico; use o humano para o que é conceitual.
“Code Smells acumulados produzem perda de familiaridade e medo de alterar. Não é estética. É previsibilidade operacional.
Code Smells acumulados produzem dois efeitos previsíveis:
Perda de familiaridade. Cada autor escreve no seu estilo. Sem padrão, cada arquivo vira uma surpresa. Onboarding fica longo. Trocar de área do sistema vira um projeto.
Medo de alterar. Quando o código está cheio de Feature Envy, Long Method, Shotgun Surgery, qualquer mudança tem efeito colateral imprevisível. O time desenvolve uma cautela excessiva — e essa cautela vira lentidão.
Eliminar smells sistematicamente impõe um padrão. O resultado é o "código que parece escrito por uma única pessoa" mesmo num time de 50 devs. Não é estética. É previsibilidade operacional.
Code Smells são detectados antes dos testes rodarem — direto no commit, no pre-commit hook ou no PR check. Isso significa:
A IA generativa reproduz os smells do código no qual opera. Não corrige Long Method — continua adicionando à função existente, porque é mais barato pra ela do que decompor responsabilidades. Não corrige Feature Envy — replica o padrão porque não conhece o domínio do negócio. Não evita smells idiomáticos como any em TypeScript ou null em Java — usa o que já está acostumada a ver na base.
Código limpo de smells, com modularização clara e padrões consistentes, faz a IA trabalhar com você. Ela reconhece convenções, reutiliza componentes existentes e gera código que se encaixa. A análise estática contínua de smells virou pré-condição para extrair valor de IA generativa.
Code Smells aumentam a probabilidade de bugs. O próximo post da série fala de outra métrica que detecta o bug antes de ele acontecer — Bug Analysis encontra erros lógicos por análise estática, sem precisar executar uma linha de código.
Bug Analysis→A Codurance acompanha times de engenharia que querem instrumentar a saúde do código sem virar gestores. Ajudamos Tech Leads e Staff Engineers a integrar análise estática em pre-commit hooks, definir thresholds de smells por severidade e estabelecer rituais de refatoração que mantêm a propriedade de "familiaridade" no código ao longo do tempo.
Se você quer aplicar essas práticas no seu time, entre em contato hoje.