Comentário Bom é Comentário Verificado: Um Pipeline de Documentação Automática que Não Mente Sobre o Código
Você já deve ter vivido essa cena: alguém abre um método público sem docstring, olha o nome da função, tenta adivinhar o comportamento pelos parâmetros e, na dúvida, faz um print no meio do código só para confirmar o que ele realmente retorna. Meia hora depois, descobre que a função tem um efeito colateral que ninguém documentou — ela grava em cache, dispara um evento, ou pior, muta um objeto que deveria ser imutável. O problema não é a ausência de comentários. É que ninguém confia mais neles, porque a experiência coletiva da equipe já provou, repetidas vezes, que documentação e código divergem assim que o primeiro refactor acontece.
A tentação óbvia em 2026 é jogar o problema para a IA: “gera a documentação para mim”. E funciona — no sentido de que produz texto plausível, bem formatado, com títulos e exemplos. O problema é que “plausível” e “correto” são coisas diferentes, e documentação incorreta é pior do que nenhuma documentação, porque ela engana com confiança. Este artigo mostra como montar um pipeline de documentação automática que usa IA para gerar o texto, mas usa engenharia de software convencional para garantir que esse texto continue verdadeiro — hoje e depois do próximo merge.
O problema real: documentação como artefato descartável
Em times que já adotaram assistentes de código, é comum ver dois extremos. No primeiro, ninguém documenta nada porque “a IA explica quando eu perguntar depois”. No segundo, documentação é gerada em massa uma vez, vira um commit gigante, e nunca mais é tocada — o que na prática é o mesmo problema do README desatualizado, só que com um verniz mais bonito.
O ponto central é que geração de documentação por IA resolve apenas metade do problema: a redação. A outra metade — manter a documentação sincronizada com o comportamento real do código ao longo do tempo — exige um processo, não um prompt isolado. É exatamente essa lacuna que este artigo cobre.
💡 Dica do Mestre: vale diferenciar “gerar documentação” de “gerar documentação verificável”. Ferramentas como as listadas no comparativo de assistentes de codificação de IA de 2026 focam majoritariamente na primeira parte. A segunda parte é responsabilidade sua, e é o que separa um pipeline confiável de um gerador de texto bonito.
Camada 1: geração assistida com contexto real, não com o arquivo isolado
O erro mais comum ao pedir documentação para uma IA é colar apenas a função isolada no prompt. Sem o contexto de quem chama essa função, de quais exceções ela propaga e de que contrato ela cumpre dentro do módulo, a IA inventa detalhes plausíveis — e “plausível” nesse contexto é sinônimo de “inventado”.
Um prompt de documentação eficaz precisa trazer, no mínimo: a assinatura da função, o corpo completo, os call sites relevantes e os testes existentes (se houver). Um exemplo de estrutura de prompt aplicado a uma função Python real de um sistema de cobrança:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
def aplicar_desconto(valor: float, cliente: Cliente, cupom: str | None = None) -> float: if cliente.tipo == TipoCliente.PREMIUM: valor *= 0.9 if cupom: desconto = _validar_cupom(cupom, cliente.id) if desconto is None: raise CupomInvalidoError(cupom) valor -= valor * desconto return round(max(valor, 0), 2) |
O prompt não deve pedir apenas “documente esta função”. Deve incluir o contrato completo:
|
1 2 3 4 5 6 7 8 9 10 11 |
Gere uma docstring no padrão Google Style para a função abaixo. Regras: - Descreva o comportamento observável, não implementação interna. - Liste TODAS as exceções que podem ser propagadas, incluindo as de _validar_cupom. - Indique explicitamente que o valor final nunca é negativo. - Não invente parâmetros nem retornos que não existem no código. [código completo + assinatura de _validar_cupom] |
O resultado tende a ser algo como:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
def aplicar_desconto(valor: float, cliente: Cliente, cupom: str | None = None) -> float: """Calcula o valor final aplicando desconto de cliente premium e cupom. Clientes do tipo PREMIUM recebem 10% de desconto automático antes da aplicação do cupom, se houver. O valor final é sempre arredondado para duas casas decimais e nunca é negativo. Args: valor: Valor original antes de descontos. cliente: Cliente associado à compra, usado para verificar tipo e validar o cupom. cupom: Código de cupom opcional. Se None, nenhum desconto adicional é aplicado. Returns: Valor final com descontos aplicados, arredondado e nunca negativo. Raises: CupomInvalidoError: Se o cupom informado não for válido para o cliente. """ |
Note que a instrução “não invente parâmetros” não é decorativa. É a defesa mais barata contra o problema mais comum de documentação gerada por IA: adicionar comportamento que soa razoável, mas que não existe — como assumir que a função trata cupons expirados quando isso nunca foi implementado.
Camada 2: verificação automática — o passo que a maioria pula
Gerar é a parte fácil. Verificar é a parte que transforma documentação em ativo confiável. Existem três verificações que valem a pena automatizar em qualquer pipeline:
1. Consistência de assinatura
A verificação mais barata é garantir que os parâmetros documentados batem exatamente com a assinatura real da função. Em Python, isso pode ser feito com a própria stdlib combinando inspect com parsing da docstring:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import inspect import re def verificar_parametros_documentados(func) -> list[str]: assinatura = inspect.signature(func) parametros_reais = set(assinatura.parameters.keys()) - {"self"} docstring = inspect.getdoc(func) or "" parametros_doc = set(re.findall(r"^\s*(\w+):", docstring, re.MULTILINE)) faltando = parametros_reais - parametros_doc sobrando = parametros_doc - parametros_reais erros = [] if faltando: erros.append(f"Parâmetros sem documentação: {faltando}") if sobrando: erros.append(f"Parâmetros documentados mas inexistentes: {sobrando}") return erros |
Rodar essa verificação em CI para todo o módulo público é barato e pega o erro mais comum: refatorar a função e esquecer de atualizar a docstring — ou, no caso de geração por IA, a IA inventar um parâmetro que não existe na assinatura real.
2. Exceções documentadas versus exceções realmente lançadas
Esta é a verificação que mais evita dor de cabeça em produção. Um analisador estático simples pode varrer o corpo da função em busca de raise e comparar com o que está descrito na seção Raises:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import ast def extrair_excecoes_lancadas(codigo_fonte: str, nome_funcao: str) -> set[str]: arvore = ast.parse(codigo_fonte) excecoes = set() for node in ast.walk(arvore): if isinstance(node, ast.FunctionDef) and node.name == nome_funcao: for sub in ast.walk(node): if isinstance(sub, ast.Raise) and sub.exc: if isinstance(sub.exc, ast.Call): excecoes.add(getattr(sub.exc.func, "id", "Desconhecida")) return excecoes |
Esse tipo de checagem estática não substitui um linter completo, mas serve como rede de segurança específica para o problema de documentação: a IA descreveu uma exceção que o código não lança, ou — pior — o código lança uma exceção que ninguém documentou, e o time só descobre isso em produção.
3. Exemplos de código executáveis (doctest como contrato)
Sempre que a IA gerar um exemplo de uso dentro da docstring, esse exemplo deve ser executável e testado, não apenas ilustrativo. Usar doctest transforma a documentação em teste de regressão:
|
1 2 3 4 5 6 7 8 9 10 11 |
def aplicar_desconto(valor: float, cliente: Cliente, cupom: str | None = None) -> float: """Calcula o valor final aplicando desconto de cliente premium e cupom. Exemplo: >>> cliente = Cliente(tipo=TipoCliente.PREMIUM) >>> aplicar_desconto(100.0, cliente) 90.0 """ |
Rodar python -m doctest -v arquivo.py em CI garante que, se o comportamento mudar (por exemplo, o desconto premium passar de 10% para 15%), o pipeline quebra imediatamente — não seis meses depois, quando alguém confiar cegamente no exemplo desatualizado.
Camada 3: pipeline em CI — do commit ao README atualizado
Com geração e verificação definidas, o próximo passo é orquestrar isso como parte do fluxo de integração contínua, não como uma tarefa manual eventual. Um desenho comum de pipeline:
- Ao abrir um pull request, um job identifica funções/métodos públicos alterados sem docstring ou com docstring desatualizada (usando as verificações da camada 2).
- Para os casos sinalizados, um agente de IA gera uma proposta de docstring com o contexto completo da função e dos testes.
- A proposta é adicionada como sugestão de commit no próprio PR — nunca aplicada automaticamente sem revisão humana.
- O desenvolvedor aceita, ajusta ou rejeita a sugestão como faria com qualquer sugestão de code review.
- Um job separado, rodando em paralelo, executa as verificações de consistência (assinatura, exceções, doctest) contra a versão final aceita.
Um exemplo simplificado de step de GitHub Actions que roda a verificação de consistência antes do merge:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
name: Verificacao de Documentacao on: pull_request: paths: - "**/*.py" jobs: docs-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configurar Python uses: actions/setup-python@v5 with: python-version: "3.12" - name: Rodar verificador de docstrings run: python scripts/verificar_docs.py --strict - name: Rodar doctests run: python -m doctest -v src/**/*.py |
A separação entre “geração automática” e “aplicação automática” é deliberada. Deixar a IA gerar texto e propor é ganho de produtividade real. Deixar a IA aplicar sem revisão em documentação de API pública é o mesmo risco de deixar código gerado por IA subir direto para produção sem revisão — um tema já bastante discutido quando se fala em confiar cegamente em saída de modelo de linguagem.
Documentação de nível superior: READMEs e diagramas de arquitetura
Docstrings resolvem o nível de função. Mas READMEs, guias de arquitetura e diagramas de fluxo têm um problema diferente: eles descrevem decisões e relações entre módulos, não apenas comportamento local. Aqui, a abordagem de geração muda: em vez de dar o código inteiro para a IA de uma vez (o que estoura contexto e produz generalizações vagas), o mais eficaz é gerar a documentação em camadas, seguindo a estrutura real do projeto.
Um fluxo prático que funciona bem:
- Gerar primeiro um resumo por módulo (responsabilidade, dependências de entrada e saída), usando apenas as assinaturas públicas e os imports.
- Consolidar esses resumos em um documento de arquitetura de mais alto nível, agora com contexto agregado em vez do código bruto.
- Gerar diagramas (por exemplo, em Mermaid) a partir do grafo de dependências real, extraído estaticamente do código, não “imaginado” pela IA.
Um exemplo de extração de grafo de dependências em um projeto Node.js/TypeScript, usando análise estática simples para alimentar o prompt com fatos, não suposições:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import { Project } from "ts-morph"; const project = new Project({ tsConfigFilePath: "tsconfig.json" }); const grafo: Record = {}; for (const arquivo of project.getSourceFiles("src/**/*.ts")) { const imports = arquivo.getImportDeclarations() .map(imp => imp.getModuleSpecifierValue()); grafo[arquivo.getBaseName()] = imports; } console.log(JSON.stringify(grafo, null, 2)); |
Esse JSON, e não o código-fonte completo, é o que deve alimentar o prompt de geração do diagrama de arquitetura. É uma aplicação direta do mesmo princípio de RAG aplicado à documentação: dar à IA fatos extraídos mecanicamente do sistema, em vez de deixar que ela infira a arquitetura a partir de uma leitura parcial e propensa a alucinação.
💡 Dica do Mestre: discussões da comunidade sobre geradores de documentação com IA, como a relatada no projeto compartilhado no r/Python, mostram um padrão recorrente: ferramentas que analisam a base de código inteira antes de gerar texto produzem resultado significativamente mais confiável do que as que trabalham arquivo por arquivo sem contexto agregado.
Armadilhas comuns e como depurá-las
Documentação “correta hoje, mentirosa amanhã”
O erro mais silencioso é tratar a geração como evento único. Sem verificação em CI, a documentação gerada por IA tem exatamente a mesma vida útil da documentação escrita manualmente: válida até o primeiro refactor não acompanhado. A solução não é gerar melhor — é verificar continuamente, como mostrado nas camadas 2 e 3.
Excesso de confiança em ferramentas de “one-click documentation”
Ferramentas que prometem documentar um repositório inteiro com um clique são úteis para gerar o rascunho inicial, mas raramente capturam nuances de segurança, contratos implícitos e efeitos colaterais que só existem no histórico de decisões do time. Comparativos como o de ferramentas de IA para código seguro em 2026 reforçam um ponto relevante: ferramentas voltadas a segurança e qualidade tendem a ser mais conservadoras na geração automática exatamente porque erros de documentação em código sensível têm custo alto — o mesmo raciocínio vale para documentação técnica em geral.
Prompt genérico para código com regras de negócio específicas
Pedir “documente esta classe” para uma classe de domínio complexo, sem explicar as invariantes de negócio, produz documentação tecnicamente correta e inutilmente genérica. O prompt precisa carregar o “porquê”, não só o “o quê” — inclusive citando regras de negócio que estão em tickets, especificações ou comentários de commit anteriores.
Falta de rastreabilidade entre documentação e decisão original
Quando a documentação gerada por IA não referencia a decisão de arquitetura que a originou (um ADR, um ticket, uma discussão de design), ela se torna descritiva, mas não explicativa. Vincular a docstring ou o trecho de README ao artefato de decisão correspondente — mesmo que seja apenas um link para o ticket — evita que a próxima pessoa precise reconstruir o raciocínio do zero.
Um checklist prático para adotar hoje
- Nunca gerar docstring apenas com a função isolada — sempre incluir call sites e testes no prompt.
- Automatizar verificação de consistência entre assinatura real e parâmetros documentados.
- Automatizar verificação entre exceções lançadas de fato e exceções documentadas.
- Transformar exemplos de docstring em doctests executáveis sempre que possível.
- Gerar documentação de arquitetura a partir de grafos de dependência extraídos estaticamente, não de leitura ingênua de código pela IA.
- Tratar sugestão de documentação como sugestão de code review — sempre com revisão humana antes do merge.
Junte-se à comunidade
Se você quer trocar experiências reais sobre como estruturar pipelines de documentação, revisão de código gerado por IA e automações que realmente sobrevivem ao uso em produção, vale participar da Comunidade Dev’s AI. É um espaço para discutir esse tipo de decisão de engenharia com quem enfrenta os mesmos problemas no dia a dia — sem o discurso de vendedor de ferramenta.
Conclusão
Documentação automática com IA não é sobre economizar tempo de digitação — isso qualquer gerador de texto faz. O valor real está em construir um pipeline onde a geração é apenas o primeiro passo de um processo maior de verificação contínua, que trata documentação com o mesmo rigor que se trata código: com testes, com CI, com revisão humana antes de mesclar. O time que aplica esse rigor ganha documentação que envelhece bem. O time que apenas gera texto bonito ganha um novo tipo de dívida técnica, só que camuflada de solução.