Nomes que mentem: o problema mais comum em bases de código antigas
1. Por que nomes importam: a linguagem do código como documentação viva
1.1. O custo de um nome enganoso: horas de debug e suposições erradas
Em bases de código antigas, o maior vilão não é tecnologia obsoleta ou falta de testes — são nomes que mentem. Um nome enganoso pode custar horas de debug para uma equipe inteira. Considere este exemplo clássico:
function processData(input) {
// 200 linhas depois...
// O nome sugere processamento, mas na verdade envia e-mail
enviarEmail(input);
return true;
}
O desenvolvedor que chama processData espera processamento de dados, não efeitos colaterais de envio de e-mail. O resultado? Bugs intermitentes, suposições erradas e retrabalho.
1.2. Código lido 10x mais do que escrito: a carga cognitiva de desvendar intenções
Estima-se que código é lido cerca de 10 vezes mais do que escrito. Cada nome mentiroso força o leitor a abrir a implementação para descobrir o que realmente acontece. Isso quebra o fluxo de leitura e aumenta a carga cognitiva.
// Nome que mente: parece que valida, mas na verdade modifica estado
function isValid(user) {
user.ultimoAcesso = new Date(); // Efeito colateral!
return user.ativo && !user.bloqueado;
}
1.3. A diferença entre um nome descritivo e um nome "técnico" que esconde o propósito
Nomes descritivos revelam intenção; nomes "técnicos" escondem propósito. Compare:
// Nome técnico que mente: foca no "como", não no "quê"
function somarPesoEViaCep(itens, cep) { ... }
// Nome descritivo: foca no "quê"
function calcularFrete(itens, cep) { ... }
2. As três categorias clássicas de nomes que mentem
2.1. Nomes genéricos demais
data, info, temp, manager — esses nomes são tão vagos que não comunicam absolutamente nada:
function saveData(data) {
// Que dados? Salvar onde? Em banco, arquivo, cache?
banco.insert('logs', data);
}
2.2. Nomes que viraram sinônimos de outra coisa
O nome diz uma coisa, a implementação faz outra:
function getUsers() {
// "get" sugere leitura, mas aqui há escrita
const usuarios = api.fetch('/users');
cache.set('usuarios', usuarios); // Efeito colateral não documentado
return usuarios;
}
2.3. Nomes que ficaram para trás em refatorações
Refatorações mal documentadas criam nomes órfãos:
function deleteTempFiles() {
// Antigamente deletava, agora apenas arquiva
moverParaLixeira('/tmp/arquivos');
registrarAuditoria('Arquivos arquivados');
}
3. O efeito dominó: como um nome mentiroso contamina o sistema inteiro
3.1. Propagação de suposições incorretas
Quando um nome mente, a mentira se propaga:
// Módulo A: função com nome enganoso
function getTaxa() { return calcularTaxaComDesconto(); }
// Módulo B: assume que é taxa bruta
function calcularTotal(valor) {
return valor * getTaxa(); // Erro! Já tem desconto aplicado
}
3.2. A síndrome do "funciona, mas ninguém sabe por quê"
Nomes que mentem criam código que funciona por coincidência:
function validateOrder(order) {
// Nome sugere validação, mas também aplica regras de negócio
order.desconto = order.valor > 100 ? 0.1 : 0;
return order.valor > 0;
}
3.3. Quando a mentira vira "verdade"
Novos desenvolvedores codificam baseados no nome, não na implementação:
// Time assume que "cache" é rápido, mas na verdade é chamada HTTP
function getCachedData(key) {
return http.get(`https://api.externa.com/cache/${key}`);
}
4. Técnicas práticas para detectar nomes mentirosos em bases legadas
4.1. Análise de frequência
Busque funções cujo nome não corresponde ao uso real:
# Grep reverso: onde "getUser" é chamado sem esperar efeitos colaterais?
grep -r "getUser" src/ | grep -v "await\|\.then"
4.2. O teste do "leigo"
Chame um colega não familiarizado com o módulo e pergunte: "O que essa função faz baseado apenas no nome?" Se ele errar, o nome mente.
4.3. Ferramentas de busca e grep reverso
# Encontre funções com "delete" no nome que não deletam
grep -r "def delete\|function delete" src/ | while read line; do
if ! grep -q "delete\|remove\|drop" <<< "$line"; then
echo "Possível mentira: $line"
fi
done
5. Quando corrigir (e quando não): priorizando renomeações com impacto
5.1. O dilema do refactor: renomear quebra contratos de API?
Estratégias seguras incluem aliases e depreciação:
// Função antiga (depreciada)
function getUsersOld() {
return getUsersNew();
}
// Nova função com nome correto
function fetchUsers() {
return api.get('/users');
}
5.2. Prioridade máxima: nomes em interfaces públicas
Interfaces públicas que outros times consomem merecem atenção imediata:
// Endpoint público com nome enganoso
// GET /api/obter-usuarios → na verdade retorna apenas admins
// Correção: criar novo endpoint e depreciar o antigo
// GET /api/obter-admins
5.3. Quando aceitar o nome mentiroso
Código morto, prestes a ser substituído, ou sem cobertura de testes:
// Código legado sem testes e prestes a ser substituído
// Aceitamos o nome mentiroso temporariamente
function getOldData() { ... } // Não tocar, será removido mês que vem
6. Estratégia de migração gradual: como desmentir nomes sem parar o time
6.1. Criação de "pontes semânticas"
Novo nome + wrapper com log de aviso:
// Ponte semântica
function calcularTotalComDesconto(pedido) {
console.warn('DEPRECIADO: use calcularTotal()');
return calcularTotal(pedido);
}
function calcularTotal(pedido) {
return pedido.itens.reduce((acc, item) => acc + item.preco, 0);
}
6.2. Renomeação em camadas
- Variáveis locais → 2. Funções internas → 3. APIs públicas
// Passo 1: Renomear variável local
function processar() {
const dadosCliente = obterDados(); // Antes: "data"
}
// Passo 2: Renomear função interna
function obterDadosCliente() { ... } // Antes: "getData"
// Passo 3: Renomear API pública (com bridge)
function obterDadosCliente() { ... }
function getData() { return obterDadosCliente(); } // Bridge
6.3. Uso de lint personalizado
# Regra de lint: bloquear nomes vagos sem descrição
# .eslintrc.json
{
"rules": {
"id-denylist": ["error", "data", "info", "temp", "manager", "utils"]
}
}
7. Prevenção: como evitar que novos nomes mentirosos entrem na base
7.1. Code review com checklist específico de nomenclatura
Checklist de code review:
- [ ] O nome descreve o quê, não o como?
- [ ] O nome revela efeitos colaterais?
- [ ] Um júnior entenderia o propósito?
7.2. Nomeie por intenção, não por implementação
// Ruim: foca na implementação
function somarPesoEViaCep(itens, cep) { ... }
// Bom: foca na intenção
function calcularFrete(itens, cep) { ... }
7.3. Cultura de "nomeie como se fosse explicar para um júnior amanhã"
// Se você precisa explicar o que a função faz, o nome está errado
function process() { /* ... */ } // Ruim
function gerarRelatorioMensal() { /* ... */ } // Bom
Referências
- Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin) — Capítulo 2 sobre nomes significativos e a importância de nomes que revelam intenção
- Refactoring: Improving the Design of Existing Code (Martin Fowler) — Técnicas de refatoração incluindo renomeação de funções e variáveis
- Code Complete (Steve McConnell) — Seção sobre gerenciamento de nomes em bases de código grandes
- The Art of Readable Code (Dustin Boswell, Trevor Foucher) — Princípios de nomenclatura que evitam ambiguidades
- ESLint - id-denylist Rule — Documentação oficial da regra que permite banir nomes vagos como "data" e "info"
- Google's Code Review Guidelines - Naming — Práticas de Google para revisão de nomes em code reviews
- Mozilla Developer Network - Coding Style — Guia de estilo com exemplos de nomenclatura descritiva