{"id":1094,"date":"2026-08-13T04:01:36","date_gmt":"2026-08-13T07:01:36","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/refatoracao-assistida-por-ia-em-sistemas-vivos-sem-perder-controle\/"},"modified":"2026-08-13T04:01:43","modified_gmt":"2026-08-13T07:01:43","slug":"refatoracao-assistida-por-ia-em-sistemas-vivos-sem-perder-controle","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/refatoracao-assistida-por-ia-em-sistemas-vivos-sem-perder-controle\/","title":{"rendered":"Refatorando com IA em Sistemas Vivos: Como Delegar Sem Perder o Controle da Base de C\u00f3digo"},"content":{"rendered":"<p>Voc\u00ea pede para a IA &#8220;refatorar essa classe para deixar o c\u00f3digo mais limpo&#8221;. Ela devolve um diff enorme, elegante, com nomes melhores, fun\u00e7\u00f5es menores, padr\u00f5es de projeto aplicados com propriedade. Voc\u00ea aprova, faz o merge, sobe para homologa\u00e7\u00e3o. Duas horas depois, o time de suporte reporta que um relat\u00f3rio financeiro que dependia de um efeito colateral sutil \u2014 um campo que era populado como side effect de uma fun\u00e7\u00e3o com nome p\u00e9ssimo, mas comportamento correto \u2014 parou de funcionar. A IA n\u00e3o quebrou uma regra de neg\u00f3cio: ela quebrou um contrato impl\u00edcito que ningu\u00e9m tinha documentado, porque ningu\u00e9m sabia que ele existia.<\/p>\n<p>Esse \u00e9 o risco central de usar IA para refatorar sistemas que j\u00e1 est\u00e3o em produ\u00e7\u00e3o, com hist\u00f3rico, depend\u00eancias cruzadas e comportamentos &#8220;acidentais&#8221; que se tornaram requisitos ao longo do tempo. A IA \u00e9 excelente em reescrever c\u00f3digo isolado. Ela n\u00e3o tem, por padr\u00e3o, vis\u00e3o do sistema como um organismo vivo \u2014 e \u00e9 exatamente a\u00ed que projetos s\u00e3o quebrados silenciosamente. Neste artigo, vamos tratar refatora\u00e7\u00e3o assistida por IA n\u00e3o como &#8220;pedir para limpar o c\u00f3digo&#8221;, mas como um processo de engenharia com escopo definido, rede de seguran\u00e7a e revis\u00e3o em camadas \u2014 a \u00fanica forma de fazer isso em escala sem introduzir regress\u00f5es.<\/p>\n<h2>Por que refatora\u00e7\u00e3o com IA \u00e9 diferente de gera\u00e7\u00e3o de c\u00f3digo com IA<\/h2>\n<p>Gerar c\u00f3digo novo \u00e9 um problema de cria\u00e7\u00e3o: voc\u00ea define um contrato (assinatura, comportamento esperado) e a IA preenche a implementa\u00e7\u00e3o. Se ela errar, o pior cen\u00e1rio \u00e9 reescrever a fun\u00e7\u00e3o. Refatorar \u00e9 um problema de <strong>preserva\u00e7\u00e3o<\/strong>: existe um comportamento observ\u00e1vel hoje, muitas vezes n\u00e3o totalmente especificado, e a tarefa \u00e9 mudar a estrutura interna sem mudar esse comportamento.<\/p>\n<p>O problema \u00e9 que &#8220;comportamento observ\u00e1vel&#8221; inclui coisas que raramente est\u00e3o em nenhum lugar escrito:<\/p>\n<ul>\n<li>Ordem de execu\u00e7\u00e3o que afeta race conditions em sistemas concorrentes.<\/li>\n<li>Efeitos colaterais em logs, m\u00e9tricas ou eventos que outros sistemas consomem.<\/li>\n<li>Tratamento de exce\u00e7\u00f5es que, mesmo &#8220;errado&#8221;, \u00e9 o que o resto do sistema espera.<\/li>\n<li>Comportamento de borda (null, string vazia, lista vazia) que ningu\u00e9m testou explicitamente, mas que existe em produ\u00e7\u00e3o.<\/li>\n<\/ul>\n<p>A IA, ao refatorar, tende a &#8220;corrigir&#8221; essas inconsist\u00eancias porque elas parecem bugs do ponto de vista da leitura est\u00e1tica do c\u00f3digo. Do ponto de vista do sistema em produ\u00e7\u00e3o, elas s\u00e3o comportamento contratual.<\/p>\n<blockquote><p><strong>\ud83d\udca1 Dica do Mestre:<\/strong> Michael Feathers, no cl\u00e1ssico <em>Working Effectively with Legacy Code<\/em>, define c\u00f3digo legado como &#8220;c\u00f3digo sem testes&#8221;. Sob essa defini\u00e7\u00e3o, praticamente todo c\u00f3digo que uma IA vai refatorar em um projeto real \u00e9 legado \u2014 mesmo que tenha sido escrito h\u00e1 um m\u00eas. A pergunta certa antes de refatorar n\u00e3o \u00e9 &#8220;esse c\u00f3digo \u00e9 antigo?&#8221;, \u00e9 &#8220;esse c\u00f3digo tem uma rede de seguran\u00e7a que detecta se eu mudei o comportamento?&#8221;.<\/p><\/blockquote>\n<h2>O framework: escopo, rede de seguran\u00e7a, execu\u00e7\u00e3o, revis\u00e3o<\/h2>\n<p>Refatora\u00e7\u00e3o segura assistida por IA segue quatro etapas que n\u00e3o podem ser puladas. Pular a etapa 2 \u00e9 a causa mais comum de incidentes.<\/p>\n<h3>1. Delimitar o escopo antes de escrever qualquer prompt<\/h3>\n<p>O erro mais comum \u00e9 pedir refatora\u00e7\u00f5es amplas demais: &#8220;melhora essa classe&#8221;, &#8220;modulariza esse arquivo&#8221;. Isso d\u00e1 \u00e0 IA liberdade para tocar em partes do c\u00f3digo que voc\u00ea n\u00e3o revisou mentalmente antes de pedir a mudan\u00e7a. Refatora\u00e7\u00e3o segura tem escopo de diff pequeno e objetivo nomeado.<\/p>\n<p>Compare os dois pedidos:<\/p>\n<pre><code>\u274c \"Refatore o arquivo OrderService.java para ficar mais limpo e seguir boas pr\u00e1ticas.\"\n\n\u2705 \"Extraia o m\u00e9todo calculateShippingCost() da classe OrderService para uma nova\nclasse ShippingCalculator. Mantenha a assinatura p\u00fablica de OrderService.calculateTotal()\nid\u00eantica. N\u00e3o altere nenhuma outra l\u00f3gica no arquivo. N\u00e3o altere imports n\u00e3o relacionados\na essa extra\u00e7\u00e3o.\"<\/code><\/pre>\n<p>O segundo prompt tem um objetivo \u00fanico, um limite expl\u00edcito (&#8220;n\u00e3o altere nenhuma outra l\u00f3gica&#8221;) e preserva um contrato p\u00fablico que outras partes do sistema dependem. Isso reduz drasticamente a superf\u00edcie de erro e \u2014 igualmente importante \u2014 reduz a superf\u00edcie que voc\u00ea precisa revisar com aten\u00e7\u00e3o.<\/p>\n<h3>2. Construir a rede de seguran\u00e7a: testes de caracteriza\u00e7\u00e3o antes de tocar no c\u00f3digo<\/h3>\n<p>Se o c\u00f3digo n\u00e3o tem testes, escrever testes de comportamento (n\u00e3o de implementa\u00e7\u00e3o) antes de refatorar \u00e9 obrigat\u00f3rio \u2014 e a IA pode ajudar exatamente nisso, de forma segura, porque gerar testes que capturam comportamento atual n\u00e3o corre o risco de &#8220;melhorar&#8221; nada.<\/p>\n<p>Testes de caracteriza\u00e7\u00e3o registram o que o c\u00f3digo faz hoje, certo ou errado, para que qualquer refatora\u00e7\u00e3o subsequente seja validada contra esse baseline.<\/p>\n<pre><code class=\"language-python\">import pytest\nfrom decimal import Decimal\nfrom order_service import OrderService\n\n# Teste de caracteriza\u00e7\u00e3o: captura o comportamento ATUAL,\n# incluindo casos de borda estranhos que existem em produ\u00e7\u00e3o.\n\ndef test_calculate_total_com_desconto_e_frete_gratis():\n    service = OrderService()\n    resultado = service.calculate_total(\n        items=[{\"price\": Decimal(\"100.00\"), \"qty\": 2}],\n        coupon=\"FRETEGRATIS10\",\n        region=\"SP\"\n    )\n    # Este valor foi capturado rodando o c\u00f3digo atual, n\u00e3o deduzido\n    # da regra de neg\u00f3cio documentada \u2014 a documenta\u00e7\u00e3o est\u00e1 desatualizada.\n    assert resultado == Decimal(\"189.00\")\n\ndef test_calculate_total_com_lista_vazia_retorna_zero_sem_exception():\n    service = OrderService()\n    resultado = service.calculate_total(items=[], coupon=None, region=\"RJ\")\n    assert resultado == Decimal(\"0.00\")\n\ndef test_calculate_total_com_regiao_invalida_nao_lanca_mas_ignora_frete():\n    # Comportamento \"estranho\" mas que o time de vendas descobriu que\n    # \u00e9 usado deliberadamente para pedidos internacionais.\n    service = OrderService()\n    resultado = service.calculate_total(\n        items=[{\"price\": Decimal(\"50.00\"), \"qty\": 1}],\n        coupon=None,\n        region=\"XX\"\n    )\n    assert resultado == Decimal(\"50.00\")\n<\/code><\/pre>\n<p>Pe\u00e7a \u00e0 IA para gerar esses testes observando o c\u00f3digo-fonte e, quando poss\u00edvel, executando-o com dados reais anonimizados. O prompt certo aqui \u00e9: &#8220;gere testes que capturem o comportamento atual desta fun\u00e7\u00e3o para todos os caminhos de execu\u00e7\u00e3o vis\u00edveis, incluindo casos de borda; n\u00e3o corrija nada que pare\u00e7a um bug, apenas documente o comportamento existente&#8221;.<\/p>\n<blockquote><p><strong>\ud83d\udca1 Dica do Mestre:<\/strong> Ferramentas de mutation testing como o <a href=\"https:\/\/pitest.org\/\" target=\"_blank\">PIT (Java)<\/a>, o <a href=\"https:\/\/mutmut.readthedocs.io\/\" target=\"_blank\">mutmut (Python)<\/a> ou o <a href=\"https:\/\/stryker-mutator.io\/\" target=\"_blank\">Stryker<\/a> (JS\/TS\/.NET) ajudam a validar se seus testes de caracteriza\u00e7\u00e3o realmente pegam mudan\u00e7as de comportamento, e n\u00e3o s\u00f3 cobrem linhas. Cobertura de linha alta com testes fracos \u00e9 a ilus\u00e3o de seguran\u00e7a mais perigosa antes de uma refatora\u00e7\u00e3o.<\/p><\/blockquote>\n<h3>3. Executar a refatora\u00e7\u00e3o em passos pequenos e revers\u00edveis<\/h3>\n<p>Depois de ter a rede de seguran\u00e7a, a execu\u00e7\u00e3o deve seguir os passos cl\u00e1ssicos de refatora\u00e7\u00e3o (extrair m\u00e9todo, mover classe, inverter depend\u00eancia) um por vez, rodando os testes entre cada passo. Isso vale tanto para refatora\u00e7\u00e3o manual quanto assistida por IA \u2014 a diferen\u00e7a \u00e9 que, com IA, cada passo pode ser um prompt isolado e revis\u00e1vel.<\/p>\n<pre><code># Fluxo de execu\u00e7\u00e3o, um commit por passo\n\ngit checkout -b refactor\/extract-shipping-calculator\n\n# Passo 1: extrair a interface, sem mudar comportamento\n# (prompt espec\u00edfico, diff pequeno, testes passam)\ngit commit -m \"extract: cria interface ShippingCalculator sem alterar comportamento\"\n\n# Passo 2: mover a implementa\u00e7\u00e3o\ngit commit -m \"extract: move calculateShippingCost para ShippingCalculator\"\n\n# Passo 3: atualizar OrderService para usar a nova classe via inje\u00e7\u00e3o\ngit commit -m \"refactor: OrderService passa a depender de ShippingCalculator\"\n\n# Testes de caracteriza\u00e7\u00e3o executam depois de CADA commit, n\u00e3o s\u00f3 no final\n<\/code><\/pre>\n<p>Se em algum passo os testes de caracteriza\u00e7\u00e3o falharem, o problema est\u00e1 isolado naquele commit espec\u00edfico \u2014 voc\u00ea n\u00e3o precisa investigar um diff gigante para descobrir onde o comportamento mudou. Essa granularidade \u00e9 o que torna o processo audit\u00e1vel e revers\u00edvel com <code>git revert<\/code> pontual, sem precisar descartar todo o trabalho.<\/p>\n<h3>4. Revis\u00e3o em camadas: sint\u00e1tica, sem\u00e2ntica e sist\u00eamica<\/h3>\n<p>Revisar um diff gerado por IA linha a linha, procurando erros de sintaxe, \u00e9 a camada mais f\u00e1cil e a menos importante \u2014 compiladores e linters j\u00e1 fazem isso. As camadas que exigem julgamento humano s\u00e3o outras duas:<\/p>\n<ul>\n<li><strong>Revis\u00e3o sem\u00e2ntica:<\/strong> o comportamento da fun\u00e7\u00e3o mudou? Use os testes de caracteriza\u00e7\u00e3o como evid\u00eancia objetiva, n\u00e3o a leitura do c\u00f3digo.<\/li>\n<li><strong>Revis\u00e3o sist\u00eamica:<\/strong> quem mais chama esse c\u00f3digo? Uma mudan\u00e7a de assinatura, mesmo compat\u00edvel, afeta contratos com outros servi\u00e7os, filas de mensagens, serializa\u00e7\u00e3o de cache, ou testes de integra\u00e7\u00e3o em outros reposit\u00f3rios?<\/li>\n<\/ul>\n<p>Um checklist pr\u00e1tico para revis\u00e3o sist\u00eamica antes de aprovar um PR de refatora\u00e7\u00e3o gerado com IA:<\/p>\n<pre><code>[ ] Assinaturas p\u00fablicas alteradas? Se sim, quem consome esse m\u00e9todo\/endpoint?\n[ ] Ordem de campos em serializa\u00e7\u00e3o (JSON, protobuf) foi preservada?\n[ ] Exce\u00e7\u00f5es lan\u00e7adas mudaram de tipo? Algum catch espec\u00edfico depende disso?\n[ ] Logs ou m\u00e9tricas emitidos foram removidos ou tiveram formato alterado?\n[ ] H\u00e1 testes de integra\u00e7\u00e3o\/E2E cobrindo o fluxo completo, n\u00e3o s\u00f3 a unidade?\n[ ] O diff toca em arquivos fora do escopo pedido no prompt?\n<\/code><\/pre>\n<p>Esse \u00faltimo ponto \u00e9 cr\u00edtico. Ferramentas como o <a href=\"https:\/\/claude.com\/product\/claude-code\" target=\"_blank\">Claude Code<\/a> e outros agentes de terminal frequentemente &#8220;aproveitam&#8221; a tarefa para corrigir imports, formata\u00e7\u00e3o ou pequenos &#8220;bugs&#8221; adjacentes que n\u00e3o foram pedidos. Isso pode ser bem-vindo em c\u00f3digo isolado, mas em sistemas com m\u00faltiplos mantenedores \u00e9 fonte de conflitos e regress\u00f5es n\u00e3o relacionadas ao objetivo do PR. Vale configurar instru\u00e7\u00f5es de projeto \u2014 em um <code>CLAUDE.md<\/code>, por exemplo \u2014 explicitando que altera\u00e7\u00f5es fora do escopo pedido devem ser reportadas, n\u00e3o aplicadas silenciosamente.<\/p>\n<h2>Exemplo pr\u00e1tico: refatorando um trecho legado em m\u00faltiplas linguagens<\/h2>\n<p>Para ilustrar que o princ\u00edpio \u00e9 generalista e n\u00e3o depende de stack, veja o mesmo padr\u00e3o de refatora\u00e7\u00e3o \u2014 extrair uma responsabilidade misturada em uma fun\u00e7\u00e3o grande \u2014 em tr\u00eas contextos diferentes.<\/p>\n<h3>TypeScript: separando valida\u00e7\u00e3o de persist\u00eancia<\/h3>\n<pre><code class=\"language-typescript\">\/\/ Antes: valida\u00e7\u00e3o e persist\u00eancia misturadas\nasync function createUser(data: UserInput): Promise {\n  if (!data.email || !data.email.includes(\"@\")) {\n    throw new Error(\"Email inv\u00e1lido\");\n  }\n  if (data.age &lt; 18) {\n    throw new Error(&quot;Usu\u00e1rio menor de idade&quot;);\n  }\n  const hashed = await bcrypt.hash(data.password, 10);\n  const user = await db.users.insert({ ...data, password: hashed });\n  await emailService.sendWelcome(user.email);\n  return user;\n}\n\n\/\/ Prompt usado: &quot;Extraia a valida\u00e7\u00e3o de UserInput para uma fun\u00e7\u00e3o pura\n\/\/ validateUserInput() que retorna um array de erros. N\u00e3o altere a ordem\n\/\/ de execu\u00e7\u00e3o do restante da fun\u00e7\u00e3o. Mantenha createUser com a mesma\n\/\/ assinatura e mesmo comportamento de exce\u00e7\u00e3o.&quot;\n\nfunction validateUserInput(data: UserInput): string[] {\n  const errors: string[] = [];\n  if (!data.email || !data.email.includes(&quot;@&quot;)) errors.push(&quot;Email inv\u00e1lido&quot;);\n  if (data.age &lt; 18) errors.push(&quot;Usu\u00e1rio menor de idade&quot;);\n  return errors;\n}\n\nasync function createUser(data: UserInput): Promise {\n  const errors = validateUserInput(data);\n  if (errors.length &gt; 0) throw new Error(errors[0]); \/\/ preserva comportamento: s\u00f3 o 1\u00ba erro\n  const hashed = await bcrypt.hash(data.password, 10);\n  const user = await db.users.insert({ ...data, password: hashed });\n  await emailService.sendWelcome(user.email);\n  return user;\n}\n<\/code><\/pre>\n<p>Note o detalhe: o comportamento original lan\u00e7ava s\u00f3 o primeiro erro encontrado, n\u00e3o todos. Um refatoramento &#8220;ing\u00eanuo&#8221; para <code>validateUserInput<\/code> retornando todos os erros e um <code>throw new Error(errors.join(\", \"))<\/code> pareceria melhor, mas mudaria o contrato de erro que talvez algum front-end esteja fazendo parsing de string para exibir mensagem espec\u00edfica. Isso s\u00f3 se detecta com teste de caracteriza\u00e7\u00e3o cobrindo m\u00faltiplos erros simult\u00e2neos.<\/p>\n<h3>Delphi: isolando regra de neg\u00f3cio de acesso a dados<\/h3>\n<pre><code class=\"language-pascal\">\/\/ Antes: regra de neg\u00f3cio e SQL na mesma unit\nfunction TPedidoService.CalcularDesconto(APedido: TPedido): Currency;\nvar\n  Query: TFDQuery;\nbegin\n  Query := TFDQuery.Create(nil);\n  try\n    Query.Connection := FConexao;\n    Query.SQL.Text := 'SELECT percentual FROM regras_desconto WHERE cliente_id = :id';\n    Query.ParamByName('id').AsInteger := APedido.ClienteId;\n    Query.Open;\n    if Query.RecordCount &gt; 0 then\n      Result := APedido.Total * (Query.FieldByName('percentual').AsFloat \/ 100)\n    else\n      Result := 0;\n  finally\n    Query.Free;\n  end;\nend;\n\n\/\/ Prompt: \"Extraia a regra de c\u00e1lculo do desconto para uma fun\u00e7\u00e3o pura que\n\/\/ receba o percentual j\u00e1 obtido, e isole o acesso a dados em um m\u00e9todo\n\/\/ separado chamado ObterPercentualDesconto. N\u00e3o altere o tratamento de\n\/\/ RecordCount = 0.\"\n\nfunction TPedidoService.ObterPercentualDesconto(AClienteId: Integer): Double;\nvar\n  Query: TFDQuery;\nbegin\n  Query := TFDQuery.Create(nil);\n  try\n    Query.Connection := FConexao;\n    Query.SQL.Text := 'SELECT percentual FROM regras_desconto WHERE cliente_id = :id';\n    Query.ParamByName('id').AsInteger := AClienteId;\n    Query.Open;\n    if Query.RecordCount &gt; 0 then\n      Result := Query.FieldByName('percentual').AsFloat\n    else\n      Result := 0;\n  finally\n    Query.Free;\n  end;\nend;\n\nfunction TPedidoService.CalcularDesconto(APedido: TPedido): Currency;\nvar\n  Percentual: Double;\nbegin\n  Percentual := ObterPercentualDesconto(APedido.ClienteId);\n  Result := APedido.Total * (Percentual \/ 100);\nend;\n<\/code><\/pre>\n<p>Aqui a extra\u00e7\u00e3o permite testar <code>CalcularDesconto<\/code> com um percentual mockado, sem precisar de banco de dados no teste \u2014 um ganho real de testabilidade, mas obtido com uma mudan\u00e7a estrutural m\u00ednima e sem alterar a regra de &#8220;sem registro, desconto zero&#8221;.<\/p>\n<h2>Quando a IA erra: padr\u00f5es de falha que voc\u00ea precisa reconhecer<\/h2>\n<p>Depois de revisar dezenas de refatora\u00e7\u00f5es geradas por IA em projetos reais, alguns padr\u00f5es de erro se repetem com frequ\u00eancia suficiente para merecer aten\u00e7\u00e3o espec\u00edfica:<\/p>\n<ul>\n<li><strong>&#8220;Corre\u00e7\u00e3o&#8221; silenciosa de bugs conhecidos-mas-necess\u00e1rios:<\/strong> a IA identifica que um comportamento \u00e9 inconsistente e o &#8220;corrige&#8221; sem avisar, mesmo quando o prompt n\u00e3o pediu corre\u00e7\u00e3o de bugs.<\/li>\n<li><strong>Perda de comportamento ass\u00edncrono\/concorrente:<\/strong> ao extrair m\u00e9todos, ordens de <code>await<\/code> ou locks podem ser sutilmente reordenadas, introduzindo race conditions que s\u00f3 aparecem sob carga.<\/li>\n<li><strong>Generaliza\u00e7\u00e3o excessiva:<\/strong> transformar um caso espec\u00edfico em uma abstra\u00e7\u00e3o gen\u00e9rica &#8220;para o futuro&#8221;, aumentando a complexidade sem necessidade imediata \u2014 o cl\u00e1ssico over-engineering, agora automatizado.<\/li>\n<li><strong>Confian\u00e7a excessiva em nomes:<\/strong> a IA \u00e0s vezes assume o que uma fun\u00e7\u00e3o faz pelo nome, sem ler a implementa\u00e7\u00e3o completa, especialmente em bases de c\u00f3digo grandes onde o contexto foi truncado.<\/li>\n<\/ul>\n<blockquote><p><strong>\ud83d\udca1 Dica do Mestre:<\/strong> Martin Fowler, em <em><a href=\"https:\/\/martinfowler.com\/books\/refactoring.html\" target=\"_blank\">Refactoring: Improving the Design of Existing Code<\/a>, \u00e9 enf\u00e1tico em um princ\u00edpio que se aplica perfeitamente \u00e0 era da IA: cada refatora\u00e7\u00e3o deve ser pequena o suficiente para ser revertida trivialmente. Se voc\u00ea n\u00e3o consegue explicar em uma frase o que um diff de refatora\u00e7\u00e3o muda, ele est\u00e1 grande demais para revisar com seguran\u00e7a \u2014 independentemente de quem o escreveu.<\/p><\/blockquote>\n<h2>Integrando ao fluxo de CI: gates autom\u00e1ticos para refatora\u00e7\u00e3o<\/h2>\n<p>Para dar escala a esse processo sem depender s\u00f3 de disciplina humana, vale configurar gates autom\u00e1ticos que bloqueiem merges de refatora\u00e7\u00e3o sem evid\u00eancia de preserva\u00e7\u00e3o de comportamento:<\/p>\n<pre><code class=\"language-yaml\"># .github\/workflows\/refactor-check.yml\nname: Refactor Safety Check\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  characterization-tests:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - name: Roda testes de caracteriza\u00e7\u00e3o\n        run: npm run test:characterization\n      - name: Verifica cobertura de muta\u00e7\u00e3o m\u00ednima nos arquivos alterados\n        run: npx stryker run --mutate \"$(git diff --name-only origin\/main...HEAD)\"\n      - name: Bloqueia se assinatura p\u00fablica mudou sem label 'breaking-change'\n        run: node scripts\/check-public-api-diff.js\n<\/code><\/pre>\n<p>O terceiro passo \u2014 verifica\u00e7\u00e3o de API p\u00fablica \u2014 pode ser implementado com ferramentas de diff de tipos (como <a href=\"https:\/\/api-extractor.com\/\" target=\"_blank\">API Extractor<\/a> no TypeScript, ou <a href=\"https:\/\/github.com\/golang\/go\/wiki\/CompatibilityGuidelines\" target=\"_blank\">an\u00e1lises de compatibilidade<\/a> em Go) que comparam a superf\u00edcie p\u00fablica antes e depois do PR, alertando automaticamente quando uma refatora\u00e7\u00e3o \u2014 humana ou de IA \u2014 exp\u00f5e uma mudan\u00e7a de contrato n\u00e3o sinalizada.<\/p>\n<h2>Participe da Comunidade Dev&#8217;s AI<\/h2>\n<p>Refatora\u00e7\u00e3o assistida por IA \u00e9 um dos temas em que a diferen\u00e7a entre &#8220;economizar horas&#8221; e &#8220;criar um incidente em produ\u00e7\u00e3o&#8221; est\u00e1 inteiramente no processo, n\u00e3o na ferramenta. Se voc\u00ea quer trocar experi\u00eancias reais sobre como outros times estruturam esse fluxo, comparar workflows de agentes e discutir armadilhas espec\u00edficas de cada stack, venha para a <a href=\"https:\/\/adrianosantos.link\/ComunidadeDevAI\" target=\"_blank\">Comunidade Dev&#8217;s AI<\/a>. \u00c9 um espa\u00e7o de desenvolvedores que aplicam IA no dia a dia de engenharia de software, com discuss\u00f5es pr\u00e1ticas sobre agentes, automa\u00e7\u00f5es, revis\u00e3o de c\u00f3digo e tudo que envolve manter qualidade em projetos reais.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>A IA n\u00e3o torna a refatora\u00e7\u00e3o mais arriscada por si s\u00f3 \u2014 ela torna vis\u00edvel uma verdade que j\u00e1 era verdadeira antes: refatorar c\u00f3digo sem rede de seguran\u00e7a sempre foi um jogo de sorte, humano ou automatizado. O que muda \u00e9 a velocidade com que erros podem ser introduzidos e a facilidade com que diffs grandes e aparentemente elegantes passam por revis\u00e3o superficial simplesmente porque &#8220;o c\u00f3digo parece mais limpo&#8221;.<\/p>\n<p>O caminho seguro n\u00e3o \u00e9 desconfiar da IA a ponto de n\u00e3o us\u00e1-la para refatora\u00e7\u00e3o \u2014 \u00e9 justamente o oposto: delegar refatora\u00e7\u00f5es com escopo estreito, protegidas por testes de caracteriza\u00e7\u00e3o, executadas em passos pequenos e revisadas em camadas que v\u00e3o al\u00e9m da sintaxe. Feito assim, a refatora\u00e7\u00e3o assistida por IA deixa de ser uma aposta e se torna o que sempre deveria ter sido: uma t\u00e9cnica de engenharia disciplinada, s\u00f3 que mais r\u00e1pida.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Voc\u00ea pede para a IA &#8220;refatorar essa classe para deixar o c\u00f3digo mais limpo&#8221;. Ela devolve um diff enorme, elegante, com nomes melhores, fun\u00e7\u00f5es menores, padr\u00f5es de projeto aplicados com propriedade. Voc\u00ea aprova, faz o merge, sobe para homologa\u00e7\u00e3o. Duas horas depois, o time de suporte reporta que um relat\u00f3rio financeiro que dependia de um [&hellip;]<\/p>\n","protected":false},"author":127,"featured_media":1095,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1094","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/127"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1094"}],"version-history":[{"count":1,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1094\/revisions"}],"predecessor-version":[{"id":1096,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1094\/revisions\/1096"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media\/1095"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}