A Arte de Ignorar Code Smells
Depois de 47 anos produzindo bugs em massa, desenvolvi um nariz refinado para code smells. E por “refinado,” quero dizer que aprendi a ignorá-los completamente. Junte-se a mim nesta jornada de negação olfativa.
O Que São Code Smells?
Code smells são padrões que sugerem que algo pode estar errado com seu código. A palavra-chave é “pode.” Martin Fowler e seus amigos adoram catalogar esses supostos problemas:
- Métodos longos
- Classes grandes
- Código duplicado
- Feature envy
- Data clumps
- Obsessão por primitivos
Sabe o que eu sinto? Segurança no emprego.
Por Que Code Smells São Na Verdade Code Perfume
| Code Smell | O Que Dizem | O Que Eu Ouço |
|---|---|---|
| Método Longo | “Difícil de entender” | “Ninguém vai mexer no meu código” |
| God Class | “Muitas responsabilidades” | “Único ponto de expertise” |
| Código Duplicado | “Pesadelo de manutenção” | “Redundância é confiabilidade” |
| Números Mágicos | “Intenção obscura” | “Óbvio se você conhece o sistema” |
| Código Morto | “Remova” | “Documentação histórica” |
Como o Chefe do Dilbert diria: “Não entendo o que você faz, portanto deve ser valioso.” Seu código incompreensível é segurança no emprego encarnada.
O Método Longo: Uma História de Amor
Minha obra-prima é um método de 3.847 linhas chamado processarTudo(). Ele:
- Valida entrada do usuário
- Conecta a 7 bancos de dados diferentes
- Chama 23 APIs externas
- Gera relatórios em PDF
- Envia emails
- Atualiza a UI
- Faz café (metaforicamente)
Alguém sugeriu que eu “extraísse métodos.” Eu perguntei: “Para quê? Métodos menores que fazem menos?” Não souberam responder. Xeque-mate.
public void processarTudo(Object... params) {
// Linha 1 de 3847
// ... (imagine mais 3845 linhas aqui)
// Linha 3847
log.info("Terminei de processar tudo");
}
Como XKCD 1513 nota, qualidade de código é subjetivo. Minhas 3.847 linhas são poesia.
Abraçando Código Duplicado
O princípio DRY (Don’t Repeat Yourself / Não Se Repita) é superestimado. Eu prefiro o princípio WET: Write Everything Twice / Escreva Tudo Duas Vezes.
Benefícios de código duplicado:
- Se uma cópia quebra, você tem backup
- Cada cópia pode evoluir independentemente
- Você pode grep funcionalidades procurando duplicatas
- Mais linhas = mais valor entregue
# user_service.py
def validar_email(email):
if '@' in email and '.' in email:
return True
return False
# order_service.py
def validar_email(email):
if '@' in email and '.' in email:
return True
return False
# notification_service.py
def validar_email(email):
if '@' in email and '.' in email:
return True
return False
# Por que extrair para um utilitário compartilhado? Aí você teria uma DEPENDÊNCIA!
A God Class: Monoteísmo para Código
“Especialistas” em orientação a objetos dizem que classes devem ter uma única responsabilidade. Mas por que adorar múltiplos deuses pequenos quando você pode ter uma classe onipotente?
Meu ApplicationManager.java faz tudo:
public class ApplicationManager {
// Operações de banco de dados
public void salvarUsuario() { }
public void deletarUsuario() { }
public void getUsuarios() { }
// Autenticação
public void login() { }
public void logout() { }
public void resetarSenha() { }
// Processamento de pagamento
public void cobrarCartao() { }
public void estornar() { }
// Email
public void enviarEmailBoasVindas() { }
public void enviarFatura() { }
public void enviarLembrete() { }
// Relatórios
public void gerarPDF() { }
public void exportarCSV() { }
// Gerenciamento de arquivos
public void uploadArquivo() { }
public void deletarArquivo() { }
// ... mais 247 métodos
}
2.341 linhas, 263 métodos, 1 classe. Isso é o ápice da programação orientada a objetos.
Números Mágicos: Realmente Mágicos
Os chamados “números mágicos” são apenas números cujo significado é óbvio para qualquer um que esteja aqui há 15 anos:
if (status === 7) {
// Todo mundo sabe que 7 significa "pendente de revisão"
timeout = 86400000; // Obviamente 24 horas em milissegundos
maxRetries = 3; // Contagem padrão de retentativas
bufferSize = 8192; // Buffer ótimo, confia
if (errorCode === 23 || errorCode === 47 || errorCode === 128) {
// Esses são os erros recuperáveis, obviamente
retry();
}
}
Constantes? Variáveis com nomes? Isso é só digitação extra. Seu cérebro deveria ser a tabela de lookup.
Feature Envy: Na Verdade Amizade
Quando um método usa mais dados de outra classe do que da sua própria, é chamado de “feature envy.” Eu chamo de networking.
class ProcessadorPedido:
def calcular_frete(self, cliente):
# Este método REALMENTE ama Cliente
if cliente.endereco.pais == "BR":
if cliente.membership.tier == "gold":
if cliente.historico.total_pedidos > 100:
if cliente.preferencias.frete_rapido:
return cliente.endereco.calcular_taxa_zona()
# ... mais 200 linhas acessando Cliente
Por que mover este método para Cliente? Aí eu teria que abrir um arquivo diferente. O horror.
Data Clumps: Na Verdade Grupos de Amigos
Quando os mesmos três ou quatro itens de dados aparecem juntos em múltiplos lugares, você poderia criar uma classe. Ou você poderia abraçar a camaradagem:
function criarUsuario(nome, sobrenome, email, telefone, rua, cidade, estado, cep) { }
function atualizarUsuario(nome, sobrenome, email, telefone, rua, cidade, estado, cep) { }
function validarUsuario(nome, sobrenome, email, telefone, rua, cidade, estado, cep) { }
function formatarUsuario(nome, sobrenome, email, telefone, rua, cidade, estado, cep) { }
8 parâmetros, 4 funções, flexibilidade infinita. Precisa adicionar um campo? Só adiciona outro parâmetro em todo lugar. Consistência!
Código Morto: Arqueologia Digital
Código comentado e funções não usadas não são “código morto.” São artefatos históricos:
// TODO: Remover isso depois da migração de 2019
// public void processamentoPagamentoAntigo() {
// // Esta era a implementação original
// // Mantendo só por precaução
// // Não delete - João disse que talvez precise
// // Na verdade acho que Maria precisa disso
// // UPDATE 2021: Talvez precisemos disso pro novo cliente
// // UPDATE 2023: Ainda aqui, ainda útil de alguma forma
// }
// Função não usada - NÃO DELETE
public void exportLegado() {
// Ninguém sabe o que chama isso
// Mas remover pode quebrar algo
// Melhor prevenir do que remediar
}
Como Catbert diria: “Qualquer coisa que você deletar será exatamente o que você vai precisar amanhã.”
Obsessão por Primitivos: Na Verdade Minimalismo
Usar primitivos em todo lugar ao invés de objetos pequenos é chamado de “obsessão por primitivos.” Eu chamo de otimização de performance:
// "Boa prática" - objetos desperdiçadores
Dinheiro preco = new Dinheiro(19.99, Moeda.BRL);
Email emailUsuario = new Email("usuario@exemplo.com");
Telefone telefone = new Telefone("+55-11-99999-0000");
// Minha abordagem - primitivos eficientes
double preco = 19.99; // Obviamente é real
String email = "usuario@exemplo.com"; // O que mais seria?
String telefone = "+55-11-99999-0000"; // Números são strings, aceita
Por que criar 47 classes wrapper quando String e int existem?
Minha Escala de Tolerância a Code Smell
| Intensidade do Cheiro | Ação Necessária |
|---|---|
| Leve odor | Ignorar completamente |
| Odor perceptível | Continuar ignorando |
| Cheiro forte | Considerar ignorar |
| Fedor avassalador | Adicionar aromatizante (comentário) |
| Código ativamente decompondo | Culpar o estagiário |
A Defesa Definitiva
Quando alguém apontar code smells no seu codebase, use o contra-argumento definitivo:
“Funciona em produção.”
É isso. Essa é a defesa. Se o código fedorento está rodando em produção sem incidentes, não está fedorento — está battle-tested.
# Este método tem 47 parâmetros, 12 variáveis globais,
# 3 try-catch aninhados, e conversa com 6 bancos de dados.
# Também lida com autenticação, logging e email.
# Revisores de código odeiam.
#
# Mas está em produção desde 2014.
# Zero bugs reportados.
# Senioridade vence.
Conclusão
Code smells são apenas a opinião de pessoas que têm tempo para refatorar. Engenheiros de verdade entregam features. Engenheiros de verdade abraçam o cheiro. Engenheiros de verdade têm purificadores de ar nos escritórios.
Da próxima vez que alguém mencionar “code smell” em uma review, responda com:
“Prefiro chamar de ‘personalidade do código.’ Conta uma história.”
E lembre-se da sabedoria do XKCD 1205: às vezes o tempo gasto reclamando de code smells excede o tempo economizado ao corrigi-los.
Seu nariz vai se adaptar. Seus padrões vão baixar. E um dia, você também vai escrever um método de 3.847 linhas e chamar de arte.
A IDE do autor parou de mostrar ícones de warning. Ela desistiu em 2016. Eles têm um entendimento.