Nomenclaturas
1. Motivação: por que nomes importam tanto?
Seção intitulada “1. Motivação: por que nomes importam tanto?”Uma boa parte do tempo de desenvolvimento de software não é gasta “escrevendo código novo”, mas lendo e entendendo código já existente. Estimativas empíricas em projetos reais apontam que a maior parte do esforço de manutenção está ligada à compreensão de código.
Nomes são a principal interface entre o código e a nossa capacidade de entendê‑lo:
- Eles indicam o que é (variáveis, classes, módulos);
- Eles indicam o que faz (funções, métodos);
- Eles carregam informação de domínio (regras de negócio, conceitos da aplicação).
Em muitos sistemas grandes, análises mostram que mais da metade das linhas é composta apenas por identificadores (nomes). Uma escolha ruim nesses elementos tem efeito cascata em toda a base de código.
Um computador não se importa se a variável se chama x, d ou diasDesdeUltimaAtualizacao. Mas para uma pessoa — ou um time — essa escolha muda completamente o esforço de leitura, revisão e evolução do sistema.
1.1. Critérios gerais de bons nomes
Seção intitulada “1.1. Critérios gerais de bons nomes”Ao longo do capítulo, vamos detalhar vários princípios, mas é útil ter um “checklist mental” inicial:
Um bom nome tende a ser:
- Descritivo: indica claramente o que representa ou o que faz.
- Consistente: segue o mesmo padrão de outros nomes no sistema.
- Não enganoso: não sugere um comportamento ou tipo diferente do real.
- Pronunciável e memorizável: facilita discussão em equipe.
- Adequado ao contexto: nível de detalhe condizente com o lugar onde é usado.
Nem sempre é possível atingir todos esses pontos de forma perfeita, mas eles servem como bússola ao revisar ou criar novos identificadores.
2. Categorias básicas de nomes em código
Seção intitulada “2. Categorias básicas de nomes em código”2.1. Substantivos para dados
Seção intitulada “2.1. Substantivos para dados”Em geral, estruturas que representam dados ou entidades devem ser nomeadas com substantivos ou locuções substantivas:
- Variáveis, campos e propriedades;
- Classes de domínio;
- Data Transfer Objects (DTOs), entidades de banco, etc.
Exemplos:
usuarioanalise_agendadevice_storageuser_profilepedidoendereco_entregaEsses nomes respondem à pergunta: “Que tipo de coisa é isso?”.
2.2. Verbos para ações
Seção intitulada “2.2. Verbos para ações”Funções e métodos representam comportamento; em programação imperativa e orientada a objetos, isso se traduz em ações sobre dados. Por isso, é natural que sejam nomeados com verbos ou locuções verbais:
save_user_profileget_user_infoget_user_datacalcular_total_pedidovalidar_documentoEsses nomes respondem à pergunta: “O que essa função faz?”.
Essa distinção entre substantivos (coisas) e verbos (ações) ajuda a manter um modelo mental claro da arquitetura: classes e estruturas de dados descrevem o mundo; funções e métodos descrevem o que acontece nele.
3. Formas típicas de nomes de funções
Seção intitulada “3. Formas típicas de nomes de funções”Caprile e Tonella analisaram bases de código reais e identificaram categorias comuns de nomes de funções. Entender essas categorias ajuda a padronizar padrões de verbo dentro de um código.
3.1. Ação indireta
Seção intitulada “3.1. Ação indireta”Nomes que representam eventos, estados ou “ganchos” (hooks):
erroron_erroron_error_callbackbefore_saveafter_commit
Geralmente aparecem em frameworks orientados a eventos, middlewares e registradores de callback.
3.2. Ação direta
Seção intitulada “3.2. Ação direta”Funções com nomes verbais simples, sem objeto explícito:
openclosekillstartstopreset
Nesse caso, o objeto implícito costuma ser o próprio contexto da classe ou o recurso associado:
arquivo.open()conexao.close()timer.reset()3.3. Ação sobre objeto
Seção intitulada “3.3. Ação sobre objeto”Nomes que incluem o objeto alvo da operação:
read_linewrite_lineenviar_emailatualizar_enderecocalcular_desconto
Esse padrão é muito útil quando uma mesma classe realiza operações distintas sobre múltiplos elementos.
3.4. Ação dupla (a evitar na maioria dos casos)
Seção intitulada “3.4. Ação dupla (a evitar na maioria dos casos)”Funções que tentam expressar duas ações diferentes:
search_and_replace_textconfirmar_e_salvarvalidar_e_enviar
Geralmente indicam violação de responsabilidade única. Em vez disso, costuma ser melhor quebrar em duas funções menores:
def search_text(...): # ...
def replace_text(...): # ...
def confirmar(): # ...
def salvar(): # ...3.5. Checagem
Seção intitulada “3.5. Checagem”Funções que retornam tipicamente um valor booleano, muitas vezes usadas em condicionais:
is_validis_emptytem_estoquepossui_acessois_valid_email
Esse padrão torna o código de chamada bastante natural:
if usuario.possui_acesso(recurso): # ...3.6. Transformação
Seção intitulada “3.6. Transformação”Funções que convertem de um formato/representação para outro:
convert_to_hexconverter_para_binarioto_jsonfrom_dtoparse_date
Exemplo:
def convert_to_hex(number: int) -> str: return hex(number)É importante que o nome deixe claro a direção da conversão (to_ / from_) para evitar ambiguidades.
4. Nomes com significado (em vez de letras soltas)
Seção intitulada “4. Nomes com significado (em vez de letras soltas)”4.1. Por que d = 50 é um problema?
Seção intitulada “4.1. Por que d = 50 é um problema?”Considere:
d = 50 # tempo decorrido em diasprint(d)Sem o comentário, o que significa d? Dias? Distância? Desconto? Karen Carpenter?
O fato de precisarmos de um comentário para explicar já indica que o nome é fraco. Melhor escrever:
# endays_since_modification = 50print(days_since_modification)
# pt-brdias_desde_modificacao = 50print(dias_desde_modificacao)Vantagens:
- O próprio nome carrega o contexto.
- Se o comentário ficar desatualizado, o nome ainda é autoexplicativo.
- Ferramentas de busca e refatoração funcionam melhor (é fácil encontrar todos os usos de
dias_desde_modificacao).
4.2. Funções com nomes ambíguos
Seção intitulada “4.2. Funções com nomes ambíguos”Compare:
#endef user(user_id): return db.get_user(user_id)
#pt-brdef usuario(id_usuario): return db.get_user(id_usuario)O nome user/usuario não indica ação. Pelo contexto, poderia tanto:
- Criar um usuário;
- Atualizar um usuário;
- Buscar um usuário;
- Validar um usuário.
Uma opção muito mais clara:
#endef get_user_by_id(user_id): return db.get_user(user_id)
#pt-brdef retorna_usuario_por_id(id_usuario): return db.get_user(id_usuario)Agora, antes de ler a implementação, sabemos exatamente a intenção da função.
4.3. Exemplo com lógica simples
Seção intitulada “4.3. Exemplo com lógica simples”def c(x, y): return x * y + 10
a = 5b = 3print(c(a, b))Descrever esse código para um colega exige explicar o que é c, o que são a e b, o que significa o + 10 etc.
Uma escrita mais alinhada com código limpo seria:
def calcular_preco_total(preco_unitario, quantidade): taxa_fixa = 10 return preco_unitario * quantidade + taxa_fixa
preco = 5quantidade = 3print(calcular_preco_total(preco, quantidade))Agora:
calcular_preco_totalindica a intenção;preco_unitario,quantidadeetaxa_fixacomunicam o papel de cada valor;- O leitor consegue antecipar o resultado antes de executar.
5. Nomes enganosos (e como evitá‑los)
Seção intitulada “5. Nomes enganosos (e como evitá‑los)”Um nome pode ser pior do que não dizer nada quando sugere algo diferente do que realmente faz ou representa.
5.1. Singular vs plural
Seção intitulada “5.1. Singular vs plural”#enaccountList = Account()
#pt-brlista_de_contas = Conta()Aqui, o nome sugere uma coleção (List, lista_de_contas), mas o objeto é apenas uma instância (Account, Conta). Isso induce erros de leitura e de uso.
Versão mais adequada:
#enaccount = Account()
#pt-brconta = Conta()O mesmo vale para:
#enstudents = Student()
#pt-bralunos = Aluno()Corrigindo:
#enstudent = Student()
#pt-braluno = Aluno()Regra prática: variáveis com um único elemento não devem estar no plural.
5.2. “Primeiro número” que na verdade é o menor
Seção intitulada “5.2. “Primeiro número” que na verdade é o menor”#endef get_first_number(numbers): return min(numbers)
#pt-brdef get_primeiro_numero(numeros): return max(numeros)first/primeiro sugere ordem, não necessariamente valor mínimo ou máximo. Uma leitura rápida poderia supor “primeiro elemento da lista”.
Melhor:
#endef get_lower_number(numbers): return min(numbers)
#pt-brdef get_menor_numero(numeros): return min(numeros)Agora o nome comunica claramente que estamos tratando de valor mínimo.
6. Faça distinções significativas entre nomes
Seção intitulada “6. Faça distinções significativas entre nomes”6.1. Sinônimos para comportamentos diferentes
Seção intitulada “6.1. Sinônimos para comportamentos diferentes”#endef delete_user(user_id): # ...
def remove_user(user_id): # ...
# pt-brdef deletar_usuario(id_usuario): # ...
def remover_usuario(id_usuario): # ...Aqui, delete/remove (ou deletar/remover) são praticamente sinônimos. Isso gera confusão:
- Qual deleta permanentemente?
- Qual marca como inativo?
- Ambos fazem a mesma coisa?
É melhor reservar verbos distintos para diferenças reais de comportamento:
#endef delete_user(user_id): # remove permanentemente do banco
def disable_user(user_id): # marca usuário como inativo
# pt-brdef deletar_usuario(id_usuario): # remove permanentemente
def desabilitar_usuario(id_usuario): # inativa usuário sem removê-lo do banco6.2. Pares de operações opostas
Seção intitulada “6.2. Pares de operações opostas”#endef login(user_id, password): # ...
def cancel(user_id): # ...
#pt-brdef logar(id_usuario, senha): # ...
def cancelar(id_usuario): # ...O par natural de login é logout, não cancel. cancel é vago: cancelar o quê? a sessão? a conta? o pedido?
Versão mais clara:
#endef login(user_id, password): # ...
def logout(user_id): # ...
# pt-brdef logar(id_usuario, senha): # ...
def deslogar(id_usuario): # ...Consistência em pares opostos ajuda a identificar rapidamente fluxos completos.
7. Nomes pronunciáveis e memorizáveis
Seção intitulada “7. Nomes pronunciáveis e memorizáveis”7.1. Evitando sequências crípticas
Seção intitulada “7.1. Evitando sequências crípticas”#enymdhms = datetime.datetime.now()
#pt-bramdhms = datetime.datetime.now()Esses nomes tentam codificar o formato da data (year-month-day-hour-minute-second / ano-mes-dia-hora-minuto-segundo), mas são difíceis de ler e pronunciar.
Melhor usar algo simples e semânticamente claro:
#entimestamp = datetime.datetime.now() # YYYY-MM-DD HH:MM:SS.mmmmmm
#pt-brtimestamp = datetime.datetime.now() # AAAA-MM-DD HH:MM:SS.mmmmmmSe for relevante, o formato pode ser descrito em um comentário, não no nome.
7.2. Nomes numéricos ou genéricos demais
Seção intitulada “7.2. Nomes numéricos ou genéricos demais”temp_55834 = 55834O nome temp_55834 não diz nada sobre o significado do número. Se for população:
population = 55834Agora, qualquer leitor entende o contexto sem precisar de documentação adicional.
8. Abreviações: quando atrapalham mais do que ajudam
Seção intitulada “8. Abreviações: quando atrapalham mais do que ajudam”Abreviações tendem a:
- Ser difíceis de pronunciar;
- Ser interpretadas de formas diferentes por pessoas diferentes;
- Perder significado fora do contexto imediato.
#endef get_df_user()
#pt-brdef recebe_usuario_pd()Aqui df e pd podem significar “data frame”, “default”, “padrao”, “pandas”, entre outras coisas.
Versão mais clara:
#endef get_default_user()
#pt-brdef recebe_usuario_padrao()Regra prática: prefira nomes completos, exceto em casos em que a abreviação seja extremamente estabelecida no domínio (id, url, http, etc.).
9. Nomes e busca no código
Seção intitulada “9. Nomes e busca no código”Nomes muito curtos são mais difíceis de localizar em buscas:
x = 3y = 20x e y aparecem em muitos contextos — inclusive em dependências externas, bibliotecas padrão e exemplos de testes.
Quando o contexto permite, use nomes um pouco mais específicos:
x_axis = 3y_axis = 20Nem sempre isso é necessário (em operações matemáticas pequenas, x e y são aceitáveis), mas em código de domínio de negócio ou em trechos longos, nomes específicos ajudam tanto a busca quanto o entendimento.
10. Prefixos e sufixos (e quando ainda fazem sentido)
Seção intitulada “10. Prefixos e sufixos (e quando ainda fazem sentido)”10.1. Tipos no nome da variável: prática ultrapassada
Seção intitulada “10.1. Tipos no nome da variável: prática ultrapassada”Em várias linguagens antigas, era comum indicar o tipo da variável no nome:
#ens_name = "John"
#pt-brs_nome = "John"Nesse caso, s_ indicaria string.
Com ferramentas modernas (IDEs, tipagem estática, inspeção de tipo em tempo de desenvolvimento), esse padrão de “Hungarian Notation” deixa de ser útil e apenas polui o nome.
Versão mais limpa:
#enname = "John"
#pt-brnome = "John"10.2. Exceções razoáveis
Seção intitulada “10.2. Exceções razoáveis”Há contextos em que prefixos ou sufixos ainda trazem clareza de papel, não de tipo. Por exemplo, distinção entre interface e implementação:
public interface IUserRepository { void save(User user);}
public class UserRepositoryImpl implements IUserRepository {}Aqui, o prefixo I e o sufixo Impl comunicam design estrutural, não tipo primitivo. Equipes podem adotar padrões semelhantes, desde que sejam consistentes em todo o projeto.
11. Carga cognitiva e mapeamento mental
Seção intitulada “11. Carga cognitiva e mapeamento mental”11.1. Simplificando onde o contexto é óbvio
Seção intitulada “11.1. Simplificando onde o contexto é óbvio”Nem todo nome precisa ser longo. Em casos simples e locais, nomes curtos são aceitáveis:
for i in range(10): print(i)Dentro de um for pequeno, i é uma convenção bem estabelecida para índice.
11.2. Onde nomes curtos prejudicam
Seção intitulada “11.2. Onde nomes curtos prejudicam”Considere:
class Usuario: def __init__(self, nome, idade, email, x, y, z, a, b): self.nome = nome self.idade = idade self.email = email self.x = x self.y = y self.z = z self.a = a self.b = bAqui, um leitor precisa constantemente voltar para a definição da classe para lembrar o que é x, y, z, a, b. Isso aumenta a carga cognitiva sem necessidade.
Idealmente, cada atributo deveria ter um nome que indicasse claramente seu papel (endereco, cpf, telefone, etc.).
11.3. Nomes grandes demais indicam responsabilidades grandes demais
Seção intitulada “11.3. Nomes grandes demais indicam responsabilidades grandes demais”#endef findArticlesWithoutTitlesThenApplyDefaultStyles ()
#pt-brdef encontrar_artigos_sem_titulos_então_aplicar_estilos_padrão ()Essa função provavelmente está fazendo mais de uma coisa: localizar artigos e aplicar estilos. O nome longo tenta descrever todas essas ações.
Melhor extrair funções menores:
#endef find_articles_without_titles(): # ...
def apply_default_styles(articles): # ...
#pt-brdef encontrar_artigos_sem_titulos(): # ...
def aplicar_estilos_padrao(artigos): # ...Além de reduzir a complexidade da função, isso aproxima o design do Princípio da Responsabilidade Única (SRP).
12. Nomes de classes e métodos
Seção intitulada “12. Nomes de classes e métodos”12.1. Classes: substantivos de domínio
Seção intitulada “12.1. Classes: substantivos de domínio”Classes de domínio, em geral, são substantivos:
User,Product,Account,Order,AddressAnalysis.Usuario,Produto,Conta,Pedido,AnaliseEndereco.
Evite nomes genéricos como:
Manager,Processor,Data,Info,Helper,Util.
Esses termos frequentemente escondem falta de clareza de responsabilidade. Em vez de UserManager, pense se não é possível ter:
UserService, com responsabilidades bem definidas;- Ou separar em serviços mais específicos (
UserRegistrationService,PasswordResetService), dependendo do tamanho do domínio.
12.2. Métodos: verbos que descrevem comportamento
Seção intitulada “12.2. Métodos: verbos que descrevem comportamento”Métodos geralmente são verbos:
post_tweetdelete_usercalculate_totalregister_new_order
Isso vale tanto para métodos de instância quanto para funções estáticas ou livres.
13. Evite “ser espertinho” com nomes
Seção intitulada “13. Evite “ser espertinho” com nomes”Nomes cheios de piadas internas, gírias locais ou referências culturais obscuras podem parecer divertidos no momento, mas:
- Dificultam a compreensão por pessoas de outras regiões/países;
- Ficam rapidamente datados;
- Prejudicam a comunicação profissional (documentação, artigos, apresentações).
Exemplo:
def jogar_granada_de_mao(usuario_id): # deleta usuário do sistema ...Esse tipo de nome pode ser engraçado em uma conversa, mas é inapropriado no código de produção. Prefira:
def deletar_usuario(usuario_id): ...14. Domínio da solução vs domínio do problema
Seção intitulada “14. Domínio da solução vs domínio do problema”14.1. Domínio da solução
Seção intitulada “14.1. Domínio da solução”Às vezes, o melhor nome não é aquele que replica a linguagem de negócio, mas sim a abstração técnica que o código está de fato modelando.
Exemplo:
- Do ponto de vista do problema: “sala de espera”.
- Do ponto de vista da solução: isso pode ser melhor representado como uma fila de elementos (
queue), com operações de enfileirar e desenfileirar.
Em vez de chamar a classe de SalaDeEspera, pode ser mais útil nomeá‑la como:
FilaDeEsperaFilaDeAtendimento
Esse nome comunica tanto o contexto de domínio (espera, atendimento) quanto a estrutura de dados subjacente (fila), facilitando o entendimento do comportamento.
14.2. Domínio do problema
Seção intitulada “14.2. Domínio do problema”Em outros casos, o mais importante é manter a linguagem ubíqua do domínio, especialmente quando:
- O código é lido por especialistas de negócio;
- A lógica implementa regras complexas e específicas;
- O vocabulário técnico é menos esclarecedor do que a terminologia de domínio.
Exemplo:
- Nome interno estranho como
IndividuoPreterido. - Melhor:
JogadorReserva, que expressa diretamente o papel em um time esportivo.
15. Contextos desnecessários e ruído em nomes
Seção intitulada “15. Contextos desnecessários e ruído em nomes”Adicionar sufixos ou prefixos redundantes também prejudica a clareza.
Exemplo: em um sistema chamado “Gerenciador de Estudantes (GE)”, nomear cada classe com sufixo GE:
ProfessorGEAlunoGECursoGE
Esse sufixo não adiciona informação relevante, apenas aumenta o tamanho dos nomes. Em geral, o contexto do pacote/módulo já identifica a que sistema aquele código pertence.
Prefira:
ProfessorAlunoCurso
16. Resumo dos principais problemas de nomenclatura
Seção intitulada “16. Resumo dos principais problemas de nomenclatura”De forma geral, um nome ruim costuma cair em uma (ou mais) das seguintes categorias:
-
Muito específico de forma inadequada
- Faltam informações importantes (
set,doIt,handlesem contexto); - Ou é longo demais, misturando várias responsabilidades (
get_all_users_with_permission_to_edit_article).
- Faltam informações importantes (
-
Muito ambíguo
- Expressa um conceito genérico demais (
inteiro,string,dados); - Tem múltiplos significados possíveis (
file,data,info); - Não é óbvio (
blowfishpara uma função de criptografia, por exemplo, sem contexto).
- Expressa um conceito genérico demais (
-
Incorreto
- Não condiz com o que a variável representa ou a função faz (nome sugere uma coisa, implementação faz outra).
-
Inconsistente
- Usa padrões diferentes para coisas semelhantes (
getUser,fetch_usuario,load_user_data); - Usa sinônimos para funções com papéis próximos (como
deletevsremovesem distinção clara).
- Usa padrões diferentes para coisas semelhantes (
17. Dicas práticas para escolher nomes melhores
Seção intitulada “17. Dicas práticas para escolher nomes melhores”- Use dicionários e tesauros para encontrar termos mais precisos:
- Reaproveite verbos e substantivos já usados no projeto para o mesmo conceito:
- Se em um lugar você usa
delete, eviteremovepara a mesma operação.
- Se em um lugar você usa
- Padronize naming conventions com o time:
- Documente em um guia de estilo interno;
- Automatize o que for possível com linters e ferramentas de análise.
- Não tenha medo de refatorar nomes:
- Renomear variáveis, funções e classes é uma das refatorações mais seguras e com maior retorno em legibilidade;
- Ferramentas modernas (IDEs, LSPs) tornam essa operação trivial.
18. Conclusão
Seção intitulada “18. Conclusão”Nesta unidade, você viu que:
- Nomenclatura é um dos fatores centrais de legibilidade em código;
- Bons nomes ajudam a reduzir a carga cognitiva, facilitar o onboarding e evitar bugs;
- Existem padrões típicos de nomes para funções, variáveis e classes, que podem ser aplicados de forma consistente;
- É preciso evitar nomes enganosos, abreviações obscuras, piadas internas e ruído desnecessário;
- A escolha entre termos do domínio da solução e do domínio do problema depende do contexto e do público do código;
- Refatorar nomes é uma prática essencial em código limpo.
Ao longo da disciplina, procure aplicar esses princípios sempre que escrever ou revisar código. Em particular, ao encontrar um trecho difícil de entender, pergunte‑se:
“Esse código está complicado porque a lógica é complexa, ou porque os nomes estão ruins?”
Muitas vezes, melhorar apenas a escolha de nomes já torna o código significativamente mais limpo, antes mesmo de qualquer grande refatoração estrutural.