Comentário bom explica por que, não repete o que a linha já diz
Aprenda a separar o comentário que envelhece mentindo do que salva a próxima pessoa: restrição externa, regra de negócio, contorno com prazo. Com exemplos em Python antes e depois.
A linha diz TIMEOUT_COTACAO_S = 2 e o comentário ao lado diz "timeout de 2 segundos". Um ano depois, alguém acha 2 segundos pouco, troca para 10 e esquece o comentário. Agora o código diz 10, o comentário diz 2, e nenhum dos dois diz o que importava: a transportadora encerra a conexão em 3 segundos, então esperar 10 só prende o checkout enquanto o cliente olha um spinner.
A resposta curta: comente o porquê, não o quê. O que a linha faz, o código já diz. O comentário que vale guarda o que o código não consegue mostrar: uma restrição externa, a regra de negócio e sua origem, o incidente que motivou a decisão, o contorno temporário e quando ele pode sair. Comentário que repete o código envelhece mentindo; apague-o ou troque por um nome melhor.
Por que o comentário que repete o código é pior do que nenhum
Código é executado e testado. Comentário não. Quando alguém muda a lógica, o teste quebra se a lógica estiver errada, mas nada quebra se o comentário ficou desatualizado. Com o tempo, todo comentário que descreve o mecanismo diverge do mecanismo.
A PEP 8, o guia de estilo do Python, diz isso de forma direta: comentário que contradiz o código é pior do que nenhum comentário, e mantê-lo atualizado deve ser prioridade quando o código muda. O problema é que comentário redundante dá trabalho de manter e não devolve nada, então ninguém mantém.
Já o porquê muda pouco. A transportadora cortar em 3 segundos é um fato do contrato, não da implementação. Você pode reescrever a função inteira, trocar de biblioteca HTTP, e o motivo continua valendo. Por isso esse tipo de comentário envelhece bem.
Antes e depois no mesmo módulo
O exemplo é o módulo de cotação de frete de uma loja. Primeiro, a versão com comentários que só narram:
import requests
# timeout de 2 segundos
TIMEOUT_COTACAO_S = 2
def cotar_frete(cep, peso_g):
# monta a url
url = "https://api.transportadora.exemplo/v2/cotacao"
# faz a requisição
resposta = requests.post(url, json={"cep": cep, "peso": peso_g}, timeout=TIMEOUT_COTACAO_S)
# verifica o status
resposta.raise_for_status()
# arredonda para cima
peso_kg = -(-peso_g // 1000)
return resposta.json()["valor"], peso_kg
Cada comentário repete a linha seguinte. Nenhum responde às perguntas que alguém faria ao mexer aqui: por que 2 segundos? Por que arredondar o peso para cima? Agora a versão que guarda o porquê:
import requests
# A transportadora encerra a conexão em 3 s (documentação da API v2).
# Com 2 s sobra margem para uma segunda tentativa antes de o checkout
# desistir e mostrar o frete padrão.
TIMEOUT_COTACAO_S = 2
URL_COTACAO = "https://api.transportadora.exemplo/v2/cotacao"
def cotar_frete(cep, peso_g):
resposta = requests.post(
URL_COTACAO,
json={"cep": cep, "peso": peso_g},
timeout=TIMEOUT_COTACAO_S,
)
resposta.raise_for_status()
return resposta.json()["valor"], peso_cobrado_kg(peso_g)
def peso_cobrado_kg(peso_g):
# A tabela da transportadora cobra por quilo iniciado: 1.001 g paga 2 kg.
return -(-peso_g // 1000)
Sobraram dois comentários, e os dois guardam informação que não estava em lugar nenhum do código. O resto virou nome: a URL ganhou uma constante, e o cálculo do peso ganhou uma função cujo nome diz o que ela entrega. O truque -(-peso_g // 1000) é divisão inteira arredondando para cima; o comentário explica a regra de negócio, não a aritmética.
A escolha do timeout também tem um motivo técnico que vale um comentário quando não for óbvio para a equipe: a biblioteca requests não aplica timeout por padrão, então sem esse parâmetro a chamada pode esperar indefinidamente, o problema descrito no guia de timeout antes do infinito.
Os comentários que merecem existir
- Restrição externa: limite do fornecedor, comportamento de um navegador, exigência de um órgão. "A Sefaz recusa lotes com mais de N notas" (com o N que você conferiu na documentação).
- Regra de negócio com origem: "Desconto máximo de 15% definido pelo financeiro em 2026, ver chamado FIN-212". Quem quiser mudar sabe com quem falar.
- Incidente que motivou a decisão: "Ordenar por id e não por data: duas notas com o mesmo segundo duplicaram a exportação no incidente de março".
- Contorno temporário com condição de saída: "A versão 4.2 da biblioteca de PDF corta a última linha; remover este ajuste quando atualizarmos". Sem a condição, o contorno vira permanente.
- Aviso de "não simplifique": quando a forma óbvia já foi tentada e falhou. "Não trocar por cache: o preço muda durante a promoção relâmpago".
- Documentação de interface pública: docstring dizendo o que a função recebe, devolve e que exceções lança, para quem vai chamar sem ler o corpo.
Os comentários que devem sair
- Paráfrase da linha: "incrementa i", "retorna o usuário".
- Código comentado: o histórico do Git guarda a versão antiga com data, autor e motivo. Bloco comentado no arquivo só confunde quem lê.
- Diário de alterações no topo do arquivo: "12/03 Fulano alterou X". Isso é o que o
git logfaz, e faz melhor. - Comentário de seção numa função gigante: "# valida cliente", "# calcula imposto", "# grava". Cada um desses blocos é uma função esperando um nome.
O último item merece atenção. Quando você sente necessidade de dividir uma função de oitenta linhas com comentários de seção, o comentário está compensando um desenho ruim. Extraia cada bloco numa função com nome que diga o efeito, como mostra o post sobre nome que não mente. O comentário some e a leitura melhora.
Um teste rápido para cada comentário
Antes de escrever ou manter um comentário, faça duas perguntas. Primeira: se eu apagar esta linha de comentário, alguém perde informação que não consegue recuperar lendo o código? Se não perde, apague. Segunda: se o código mudar de implementação amanhã, este comentário continua verdadeiro? Se não continua, provavelmente está descrevendo o quê, e não o porquê.
No review, aplique o mesmo filtro ao diff. Uma mudança que altera a lógica e deixa o comentário vizinho intocado merece uma pergunta: o comentário ainda vale?
Erros comuns
- Narrar cada linha: o arquivo dobra de tamanho, ninguém atualiza, e em meses os comentários descrevem outro programa.
- Deixar código comentado "por segurança": quem lê não sabe se aquilo é para voltar, se foi esquecido ou se é a versão certa.
- Usar comentário para justificar função enorme: o problema de estrutura continua, agora com texto em cima.
- Contorno sem condição de saída: o ajuste temporário vira regra permanente que ninguém tem coragem de remover.
- Regra de negócio sem origem: quem precisa mudar o número não sabe se foi decisão, lei ou chute, e não mexe ou mexe errado.
- Corrigir o código e não o comentário ao lado: a próxima pessoa confia no texto, que é o que se lê primeiro, e erra com confiança.
Checklist
- Todo número mágico tem nome ou comentário dizendo de onde vem.
- Nenhum comentário repete em português o que a linha seguinte faz.
- Não há blocos de código comentado no arquivo.
- Todo contorno temporário diz quando pode ser removido.
- Regras de negócio citam a origem: chamado, documento ou área responsável.
- Funções públicas têm docstring com entrada, saída e exceções.
- No review, mudanças de lógica são conferidas contra os comentários vizinhos.
Abra o arquivo que você mais editou este mês e apague mentalmente todos os comentários: o código ainda se explica, e os comentários que você sentiria falta são justamente os que dizem por quê?
Referência: https://www.python.org/dev/peps/pep-0008/#comments