Como usar IA para programar sem entregar código com bugs
Resumo
Usar IA para programar funciona quando você escreve um plano curto antes de pedir código, aponta o helper que deve ser reutilizado e revisa cada diff como se fosse de um colega novo. Os dados mostram que a sensação de velocidade engana: um estudo da METR encontrou desenvolvedores experientes cerca de 19% mais lentos com IA. Escolha a ferramenta pelo quanto você consegue verificar o resultado.
Se você quer entender como usar IA para programar sem entregar código frágil, comece pelo que acontece depois da geração. Você abre um ticket, cola a descrição numa janela de chat e recebe 200 linhas de código plausível. Compila. Dois dias depois, um revisor pergunta por que ele ignora o seu wrapper de retry, e ninguém no time sabe responder. A geração funcionou; o resto não.
Este é o fluxo que eu passo para engenheiros novos. Ele trata o modelo como um júnior rápido e confiante que nunca viu o seu repositório. E é organizado em torno do tempo de revisão, não do tempo de digitação.
A IA realmente deixa você mais rápido para programar?
Às vezes, e a resposta honesta depende da tarefa. A pesquisa Stack Overflow Developer Survey 2025 mostrou que 84% dos respondentes usam ou pretendem usar ferramentas de IA, mas apenas 33% confiam na precisão do resultado em algum grau. A queixa mais citada, com 66%, é o código que está "quase certo, mas não exatamente". Outros 45.2% dizem que depurar código gerado por IA leva mais tempo do que o esperado.
Os dados controlados são menos lisonjeiros. Em um estudo de 2025 da METR, 16 desenvolvedores experientes de código aberto trabalharam em 246 issues reais de repositórios que conheciam bem. Com IA liberada, eles terminaram cerca de 19% mais devagar, enquanto acreditavam ter sido cerca de 20% mais rápidos. A METR já publicou dados mais recentes, então trate esse número como um retrato das ferramentas do início de 2025, e não como veredito definitivo.
A conclusão não é que "IA é lenta". É que a sensação de velocidade é um instrumento ruim. Meça em minutos, do ticket até o PR mesclado, e não pela rapidez com que o primeiro rascunho apareceu na tela. Essa medição muda a pergunta: em vez de "a IA escreveu rápido?", você passa a perguntar "quanto tempo levou até o código estar pronto para ir ao ar?".

O que anotar antes de pedir qualquer coisa à IA?
Um plano, com as suas próprias palavras, em menos de dez linhas. Sem ele, o modelo preenche as lacunas com palpites próprios, que são genéricos por definição.
O meu modelo é curto:
A mudança de comportamento, em uma frase.
Os arquivos que você espera tocar, mesmo sem ter certeza.
A função ou o padrão existente que o código novo deve reutilizar.
Uma coisa que ele não pode fazer (nenhuma dependência nova, nenhuma mudança de schema).
Como você vai saber que funcionou: um teste, um curl, uma captura de tela.
O ponto 3 é o que as pessoas mais pulam, e é de onde vem a maior parte do código "quase certo". O modelo não sabe que o seu helper withRetry existe, a não ser que você o cite ou que ele consiga ler o arquivo. Por isso, vale nomear o padrão com precisão, mesmo que pareça óbvio para você.
Evite também o prompt "construa o app inteiro". Iniciantes e seniores recebem o mesmo resultado: um diff enorme que ninguém entende e um projeto inacabado.
Como é um bom prompt na prática?
Pegue uma tarefa real: o emissor de webhooks descarta eventos quando o receptor dá timeout. Um prompt fraco diz "melhore a confiabilidade dos webhooks". Um prompt utilizável se parece com um ticket:
Adicione retry com backoff exponencial em sendWebhook() em src/webhooks/sender.ts.
Reutilize withRetry() de lib/http.ts. Máximo de 4 tentativas, com jitter ativado.
Não altere a assinatura pública nem adicione dependências.
Adicione um caso de teste no vitest para um receptor que falha duas vezes e depois funciona.Esse prompt cita o arquivo, o helper a reutilizar, um limite e uma verificação. O resultado é um diff de uns 30 linhas que dá para ler de uma vez. Se o diff voltar com 150 linhas, o modelo se perdeu, e você rejeita em vez de tentar editar o estrago.
Dois truques ajudam. Primeiro, peça um plano e leia-o antes de qualquer alteração de arquivo: um plano errado custa trinta segundos, um diff errado custa dez minutos. Segundo, quando a resposta sair do trilho, repita a restrição violada em vez de discutir. "Você adicionou uma dependência nova, e a regra é nenhuma" funciona melhor do que um parágrafo de explicação.
Qual tipo de ferramenta serve para cada tarefa?
Existem três formatos, e confundi-los é o segundo erro mais comum.
Completar inline prevê as próximas linhas enquanto você digita. É bom para código repetitivo e testes em que o padrão já está na tela. Chat no editor responde perguntas sobre o código selecionado e propõe edições que você aceita trecho por trecho. Agentes recebem uma tarefa, leem arquivos, executam comandos e voltam com uma branch.
Escolha pelo quanto você consegue verificar de forma barata. Uma sugestão que você lê em dois segundos tem baixo risco. Uma execução de agente que mexe em 14 arquivos tem alto ganho potencial e alto custo de revisão. Quanto maior o raio de impacto, mais a sua revisão precisa pesar.
O Cursor é a opção centrada no editor: um fork do VS Code com completar com Tab bem feito e sessões de agente em paralelo. Vale a pena se você passa o dia inteiro no editor. Pule se o seu time padronizou o JetBrains e não pretende mudar.
O GitHub Copilot é a escolha de baixo atrito para times que já usam o GitHub, já que PRs, issues e revisão ficam no mesmo lugar. Fique atento à cobrança: ele passou para créditos por uso em junho de 2026, então o uso intenso de agentes custa mais do que sugere o preço do assento.
O Claude Code é nativo do terminal e agêntico: você delega uma refatoração ou a caça a um bug e depois revisa o resultado. Ele não tem autocomplete inline e roda apenas modelos Claude. É uma troca justa se você quer delegar por tarefa.
O Aider é a opção scriptável e nativa do git. Ele faz commit automático de cada mudança com uma mensagem, então desfazer é um git revert. Você paga somente pelos tokens do modelo, o que combina com quem quer controle sobre o custo.
Como impedir que ela ignore o seu repositório?
Dê contexto de forma deliberada. A maioria das saídas ruins se explica pelo fato de o modelo nunca ter visto o arquivo relevante.
Três hábitos ajudam. Primeiro, anexe dois ou três arquivos que definem o padrão, e não o diretório inteiro. Segundo, cole o teste que falha ou o erro literal em vez de descrevê-lo com suas palavras. Terceiro, mantenha no repositório um arquivo curto de regras (nomenclatura, tratamento de erro, bibliotecas proibidas) que a ferramenta lê a cada execução. A maioria das ferramentas de agente aceita algo assim.
# AI-RULES.md
- Erros: retorne Result, nunca lance exceção em services/
- Chamadas HTTP passam por lib/http.ts (tem retry e tracing)
- Sem novas dependências sem uma nota na descrição do PR
- Testes: vitest, ao lado do código, como *.test.tsQuatro linhas como essas eliminam uma parte surpreendente dos comentários de revisão. Elas também ajudam as pessoas.
Em um repositório que você ainda não conhece, faça perguntas antes de pedir edições. "Onde a expiração da sessão é aplicada, e quem a chama?" é um primeiro prompt melhor do que "adicione um refresh token". Você lê a resposta, abre os dois arquivos citados e só então decide o que mudar. É o mesmo ciclo de grep, blame e perguntar a alguém que você já faz, só que mais rápido.

Como revisar código gerado por IA e o que nunca delegar?
A revisão precisa ser mais lenta do que a de um colega. Um colega tem histórico com a sua base de código. O modelo não tem.
O meu checklist, em ordem:
Rode antes de ler. Um teste que você mesmo escreveu e que passa vale mais do que uma explicação convincente.
Leia os imports. Pacotes inventados e helpers desconhecidos aparecem ali primeiro.
Procure o que falta. Caminhos de erro, tratamento de null, limpeza de recursos. Modelos escrevem bem o caminho feliz.
Confira o tamanho do diff. Se você pediu um ajuste de 10 linhas e veio um de 120, algo foi reescrito sem que você pedisse.
Apague o que você não consegue explicar. Se você não consegue defender uma linha numa revisão, ela não entra.
Mantenha o commit pequeno e a mensagem honesta. "Adiciona retry ao emissor de webhook (com IA, testes incluídos)" está bom. Esconder a origem não ajuda ninguém e torna a depuração posterior mais difícil.
Há coisas que nunca devem ser entregues à IA. Qualquer área em que estar errado é silencioso e caro: lógica de autenticação, fluxos de pagamento, migrações de dados e verificações de permissão. São lugares em que o "quase certo" passa nos testes e falha em produção. Você ainda pode usar a IA nesses pontos, mas em outro modo: peça que ela revise o seu código e liste riscos, em vez de escrever a implementação. Ler uma lista de cinco possíveis problemas custa três minutos. Ler uma migração gerada custa a tarde inteira que você passará duvidando dela.
Se você está aprendendo, existe uma segunda exclusão. Escreva a primeira versão sozinho e depois peça ao modelo que critique. Um júnior que sempre aceita a versão gerada aprende a pedir, não a programar, e a lacuna aparece no primeiro incidente em produção.
Como isso muda para um time?
A diferença entre indivíduos e times é a carga de revisão. Um desenvolvedor usando agentes pode abrir mais PRs por dia do que os revisores conseguem ler. Combinem três coisas cedo:
Um limite de tamanho. PRs com mais de algumas centenas de linhas alteradas são divididos, independentemente de quem ou do que os escreveu.
Uma norma de divulgação. Diga quando uma mudança foi assistida por IA, para que os revisores ajustem a atenção.
Um arquivo de regras compartilhado. Uma fonte única de convenções vale mais do que cinco prompts pessoais.
No onboarding, o melhor uso que vi é a leitura guiada por perguntas. Pessoas novas perguntam ao assistente onde as coisas ficam e depois verificam no código. Isso encurta a primeira semana de "quem é dono disso?" sem entregar código que elas não conseguem manter.

Um plano de primeira semana, e a leitura antes da escrita
Dia 1: use apenas o completar inline, para testes e código repetitivo. Dia 2: faça três perguntas por dia sobre a base de código no chat e verifique cada resposta. Dia 3: deixe o chat propor uma pequena edição por tarefa e leia cada trecho. Dia 4: teste um agente numa tarefa de baixo risco, como renomear uma chave de configuração em vários arquivos, numa branch separada. Dia 5: escreva o seu arquivo de regras a partir do que mais incomodou na revisão.
Acompanhe um número durante a semana: minutos desde o início de um ticket até um PR mesclado, incluindo as correções da revisão. Se ele não caiu, você descobriu onde a ferramenta não se encaixa no seu trabalho, e isso também é um resultado.
O ganho mais honesto que vi não é a geração. É a compreensão: entender um módulo desconhecido em dez minutos em vez de uma hora. Escrever código nunca foi a parte lenta do trabalho. Lentas eram a leitura, a decisão e a verificação. Aponte a ferramenta para essas etapas, mantenha o seu próprio julgamento no botão de merge, e o resto vem como consequência.