---
title: "Evitação de Refatoração"
type: "ai-smell"
slug: "refactoring-avoidance"
url: "http://localhost:3000/pt-br/ai-smells/refactoring-avoidance.md"
category: "Estrutura"
description: "Assistentes de IA empilham código novo e quase duplicado ao lado do que já existe em vez de reestruturá-lo, então a duplicação cresce e a refatoração — o retrabalho que mantém uma base de código saudável — desaparece silenciosamente."
---
# Evitação de Refatoração

> Assistentes de IA empilham código novo e quase duplicado ao lado do que já existe em vez de reestruturá-lo, então a duplicação cresce e a refatoração — o retrabalho que mantém uma base de código saudável — desaparece silenciosamente.

## Signs and Symptoms

Um revisor vê um diff que é quase inteiramente de _adições_. O modelo resolveu o prompt acrescentando uma nova função, ramo ou arquivo em vez de editar a abstração que deveria ter absorvido a mudança. Sinais reveladores:

* **Copiar-colar-com-ajustes**: uma nova função é 90% idêntica a uma existente, diferindo por um literal, um nome de campo ou um `if` a mais.
* **Quase-duplicatas paralelas**: `formatUserCsv`, `formatAdminCsv`, `formatGuestCsv` todas escrevendo à mão o mesmo loop em vez de uma única função parametrizada.
* **Proliferação de ramos em vez de extração**: um método longo ganha mais um `else if` em vez de o modelo extrair uma estratégia/tabela de consulta.
* **Reinvenção**: um `deepClone`/`debounce`/parser de datas escrito à mão quando o repositório já importa lodash, date-fns, etc. (a OX Security chama isso de "Vanilla Style".)
* **Superespecificação**: um helper hiperespecífico de uso único onde já existe um genérico a dois arquivos de distância.
* **"Bugs déjà-vu"**: a mesma correção precisa ser aplicada em três cópias porque a duplicata nunca foi consolidada (DRY).

```ts
// Existente no repositório:
function priceWithTax(items: Item[]) {
  const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
  return subtotal * 1.2; // 20% de IVA
}

// O que o modelo adiciona para o novo caso "com desconto" —
// uma segunda cópia inteira em vez de um parâmetro:
function priceWithTaxDiscounted(items: Item[], discount: number) {
  const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0); // duplicado
  return subtotal * (1 - discount) * 1.2;                          // lógica de IVA duplicada
}

```

O smell é estrutural, então é mais visível ao longo da mudança _inteira_, não em um único trecho: muito verde, pouco código movido e um scanner de duplicação acendendo nas novas linhas.

## Reasons for the Problem

**Por que os modelos produzem isso**

* **Viés aditivo do próximo token.** Um LLM completa o prompt à sua frente. Emitir um novo bloco autocontido é a continuação localmente mais provável e de menor risco; editar uma abstração distante exige manter o módulo inteiro no contexto de trabalho e prever uma edição globalmente consistente, o que é mais difícil e não é o que o prompt imediato recompensa.
* **Contexto raso do repositório.** Assistentes de codificação raramente carregam a base de código inteira. Se o modelo não consegue _ver_ o helper, a biblioteca ou a classe base existente, ele não consegue reutilizá-los — então reconstrói. O relatório da OX Security descreve isso como o efeito "Exército de Juniores": muito código localmente funcional, nenhuma memória arquitetural.
* **Refatorar é arriscado e não é recompensado.** Reestruturar mexe em código que o modelo não foi solicitado a alterar e pode quebrar chamadores e testes. Um assistente bajulador, do tipo "só faça funcionar", minimiza o raio de impacto _não mexendo_ no código que funciona — exatamente o comportamento que a OX mediu como "Evitação de Refatorações" em 80–90% do código gerado por IA, e "Superespecificação" (uso único em vez de reutilizável) em outros 80–90%.
* **Defasagem dos dados de treinamento.** O modelo pode não saber que o repositório adotou um módulo de utilidades ou atualizou uma biblioteca após seu corte, então escreve à mão o que já existe.
* **Gerar é barato, apagar é assustador.** Produzir 40 novas linhas não custa nada ao modelo; convencê-lo a apagar e consolidar 40 linhas existentes contraria seu instinto de preservação.

**Por que isso é prejudicial**

* **A duplicação se acumula.** A análise de 2025 da GitClear sobre 211 milhões de linhas alteradas constatou que as linhas copiadas/coladas subiram de \~8,3% (2021) para 12,3% (2024) — o primeiro ano em que a duplicação superou o código "movido" (refatorado) — enquanto as linhas refatoradas caíram de \~25% para menos de 10%, uma queda de cerca de 60%. Blocos de 5+ linhas duplicadas saltaram \~8x em 2024.
* **Manutenibilidade e correção.** Cada clone é um lugar onde uma correção futura pode ser esquecida — "Bugs déjà-vu," em que o mesmo defeito se repete e precisa ser corrigido N vezes (OX: 70–80% do código de IA viola os princípios de reutilização dessa forma).
* **Acúmulo de dívida técnica.** A refatoração é o retrabalho que mantém a entropia baixa; suprimi-la significa que a dívida é criada mas nunca quitada. A base de código cresce mais rápido do que melhora.
* **Carga de revisão.** Os revisores agora precisam comparar a olho blocos quase idênticos para confirmar que são _intencionalmente_ iguais, a mudança de carga cognitiva que a discussão "code smells for AI agents" do Stack Overflow descreve — o trabalho migra de escrever para revisar e consolidar.

## Treatment

**Táticas de prompting / revisão**

* **Aponte o modelo para o que já existe.** "Antes de adicionar código, procure no repositório por um helper/util/classe base existente e reutilize-o; se nenhum servir, generalize o mais próximo." Cole o módulo relevante no contexto para que ele realmente _veja_ a abstração.
* **Restrinja o formato do diff.** "Prefira editar funções existentes a adicionar novas. Se dois caminhos de código compartilham lógica, extraia uma função compartilhada (Extrair Função) em vez de duplicar."
* **Faça-o executar as ferramentas.** Exija que o assistente rode o scanner de duplicação (jscpd / PMD CPD) e o linter, e resolva quaisquer novos achados de blocos duplicados antes de declarar concluído — isso transforma um smell invisível em um portão que falha.
* **Peça a refatoração explicitamente como uma segunda etapa.** Geração e consolidação são tarefas diferentes; faça "faça funcionar," e depois um "agora aplique DRY e remova a duplicação" separado, o que os modelos lidam muito melhor quando solicitado diretamente.
* **Adicione um portão de qualidade na CI** para que a duplicação não aumente despercebida (limite de linhas duplicadas do Sonar, ou `jscpd --threshold`).

**A refatoração de fato** — nomeie os movimentos clássicos: **Extrair Função**, **Parametrizar Função** e **Subir / Substituir Condicional por Polimorfismo ou uma tabela de consulta** para eliminar o **Código Duplicado**.

```ts
// Antes: duas funções quase idênticas (refatoração evitada)
function priceWithTax(items: Item[]) {
  const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
  return subtotal * 1.2;
}
function priceWithTaxDiscounted(items: Item[], discount: number) {
  const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
  return subtotal * (1 - discount) * 1.2;
}

// Depois: Extrair Função + Parametrizar Função
const VAT = 1.2;
const subtotalOf = (items: Item[]) =>
  items.reduce((s, i) => s + i.price * i.qty, 0);

function priceWithTax(items: Item[], discount = 0) {
  return subtotalOf(items) * (1 - discount) * VAT;
}

```

Uma única fonte de verdade para o subtotal e o IVA: uma mudança futura na regra de imposto agora é uma edição de uma linha em vez de uma caça em N lugares.

## Detected by

- **jscpd** `duplication above --threshold / --min-tokens` — Detecção de copiar/colar (https://github.com/kucherenko/jscpd)
- **PMD** `Copy/Paste Detector (minimum-tokens duplication)` — CPD (https://pmd.github.io/pmd/pmd_userdocs_cpd.html)
- **SonarQube** `duplicated_lines_density / quality-gate duplicated-blocks condition` — Duplicações (https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/)
- **ESLint (eslint-plugin-sonarjs)** `sonarjs/no-identical-functions` — no-identical-functions (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-identical-functions.md)
- **ESLint (eslint-plugin-sonarjs)** `sonarjs/no-duplicate-string` — no-duplicate-string (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-duplicate-string.md)
