Publicações | Codurance

Code Duplication: você corrige o bug. Em produção, ele continua aparecendo. Sabe por quê?

Written by Sandro Mancuso | 02 jun 2026

Você corrigiu uma cópia da lógica. Existem outras duas que você não sabia que existiam. Os testes da função "oficial" passam. O caminho que o usuário X executou foi corrigido. O caminho de Y e Z, não. Bem-vindo ao perigo silencioso da duplicação.

Você corrige o bug. Em produção, ele continua aparecendo. Os logs mostram que a correção subiu. Os testes passam. Mas o cliente relata o mesmo problema na semana seguinte. Code Duplication é a métrica que explica por quê.

TL;DR

Code Duplication é a replicação do mesmo comportamento em múltiplos pontos do sistema. Diferentemente das outras métricas, o problema é espalhado — não fica concentrado em um único arquivo. O perigo maior é a falsa sensação de segurança: você corrige uma cópia, e o bug continua nas outras. Com IA generativa, o problema acelerou.

Para quem  Quem já viveu "achei que tinha corrigido" Leitura  ~6 min Funil  Awareness → Consideration

What this article explores:

  • O cenário típico: bug que volta após "correção" — uma cópia corrigida, duas outras esquecidas
  • O que conta como duplicação — quatro tipos de clones detectados por análise estática
  • Por que duplicação é diferente das outras métricas (problema espalhado, sem epicentro)
  • A falha oculta — o risco real da falsa sensação de segurança
  • Os três custos sistêmicos: persistência de bugs, desperdício cognitivo, inconsistência
  • Por que IA generativa piorou o problema — duplicação silenciosa via prompts
  • DRY vs WET — o princípio operacional, sem fanatismo
  • Plano operacional em 5 passos para começar hoje
  • Cinco pontos-chave para levar embora
§ 1 Cena

Você recebe o ticket de produção: o cliente está vendo o desconto errado. Investiga. Encontra a função calculateDiscount. Identifica o bug — uma comparação trocada. Corrige. Escreve o teste. Sobe pra staging, valida. Sobe pra produção.

Uma semana depois, o ticket volta. Mesmo cliente. Mesmo sintoma.

Você reabre. Vai no log. O método calculateDiscount que você corrigiu está sendo chamado, sim — mas existe outro lugar no sistema que não chama essa função. Em vez disso, tem uma cópia da lógica embutida diretamente no controller. Outro autor, três anos atrás, copiou e colou. Esse caminho do código nunca foi corrigido.

Esse é o cenário típico de Code Duplication. E o detalhe perverso: você não tem como saber, na hora da correção, que existem outras cópias. Os testes da função que você corrigiu passaram. O comportamento daquele caminho está correto. O problema é que outro caminho usa lógica paralela, independentemente de quantos testes você adicionar à função "oficial".

O que conta como duplicação

A definição operacional é direta: mesmo comportamento lógico em mais de um lugar, sem reuso. Não precisa ser cópia literal — análise estática moderna detecta:

Tipo 01
Cópia literal
Trecho idêntico, character-by-character.
Tipo 02
Cópia com renomeação
Mesma estrutura, variáveis renomeadas.
Tipo 03
Cópia com modificação local
Mesma estrutura, com algumas linhas adicionadas/removidas.
Tipo 04
Cópia semântica
Implementação diferente, comportamento equivalente. Mais difícil de detectar.
§ 2 Tipologia

A análise via Clone Detection roda em milhões de linhas em segundos. Ferramentas referenciais: PMD/CPD (Copy-Paste Detector), jscpd (multi-linguagem), Simian (Java/C#/Python), e a categoria de Clone Detection em ferramentas modernas de análise estática — incluindo a plataforma SQA da Codurance, que integra Code Duplication com as outras quatro métricas da série em um diagnóstico unificado.

Por que duplicação é diferente

As métricas anteriores da série — Ciclomática, Cognitiva, Smells, Bugs — medem problemas agrupados. A complexidade fica em uma função densa; o smell fica em uma classe específica; o bug lógico fica em uma linha. Você consegue apontar o lugar.

Duplicação é o oposto: o problema está espalhado. Não tem epicentro. A mesma lógica vive em N lugares, e cada um deles parece, isoladamente, normal. Você só vê o problema quando olha para o sistema como um todo.

Isso muda completamente a estratégia de remediação. Quanto à complexidade, você refatora a função problemática. Para duplicação, você precisa identificar o conjunto, escolher a "cópia autoritativa" (ou criar uma nova função que substitua todas as existentes) e migrar cada uso. É refatoração coordenada.

A metáfora do apêndice

A duplicação é como ter um braço a mais — você não precisa, mas tem que cuidar dele todo dia. Não gera valor, consome manutenção e ainda pode infeccionar (virar bug). A meta é manter a métrica próxima de zero.

A falha oculta — o risco real

A periculosidade da duplicação não está no espaço em disco que ela ocupa. Está na falsa sensação de segurança.

Cenário concreto: três cópias da mesma lógica, em três lugares diferentes. Bug é descoberto na cópia A. O dev corrige a cópia A. Roda os testes que conhece. Tudo verde. Sobe pra produção.

Fig. 1 — Correção parcial em código duplicado
Cópia A
controllers/orders.js
✓ CORRIGIDO
Path do usuário X. Testes passam. Comportamento ok.
Cópia B
services/billing.js
✗ AINDA QUEBRADO
Path do usuário Y. Bug persiste. Comportamento errado.
Cópia C
jobs/discount-batch.js
✗ AINDA QUEBRADO
Path do usuário Z. Bug persiste. Job noturno errado.
O ticket "fechado" no path A reabre na semana seguinte, vindo do path B. O dev olha o log e fica confuso — a correção foi aplicada e está em produção. Como o bug ainda existe?
§ 3 Custo

Em produção, o caminho do usuário X passa por A. Comportamento corrigido — bug resolvido. Os caminhos dos usuários Y e Z passam por B e C. Comportamento ainda errado — bug continua, intermitente, "reaparecendo".

O dev olha o log e fica confuso. A correção foi aplicada, validada e está em produção. Como o bug ainda existe? A resposta é que a correção foi parcial — e ele não tinha como saber. Os outros dois pontos de execução não estão mapeados em lugar algum.

Esse cenário gera três custos

  1. Persistência de bugs pós-correção. Erro sobrevive em cópias ocultas. Retrabalho garantido.
  2. Desperdício cognitivo. Time gasta energia analisando variações da mesma lógica em locais diferentes.
  3. Inconsistência sistêmica. O software apresenta comportamentos distintos para a mesma regra, dependendo de qual "cópia" foi executada.

O terceiro é o mais grave em sistemas com regras de negócio: a empresa promete uma coisa; o software entrega outra dependendo do caminho. Confiança quebrada.

Antes do Copilot, duplicação era escolha consciente. Com IA generativa, virou silenciosa — cada prompt potencialmente vira uma nova cópia.

§ 4 IA

A IA piorou o problema

Antes do Copilot/Cursor/Claude, a duplicação era feita por meio de copy-paste consciente. O dev sabia que estava replicando. Era uma escolha (geralmente ruim, mas uma escolha).

Com IA generativa via "prompt após prompt", a duplicação virou silenciosa. O fluxo típico:

  1. Dev pede ao LLM: "escreve uma função que calcula desconto baseado em tier do cliente"
  2. LLM gera função nova, sem consultar a base existente
  3. Dev cola, ajusta, commita

Se a base de código tem modularização clara e tipagem forte, o LLM consegue (às vezes) identificar que uma função similar já existe e reutilizá-la. Mas se a base é bagunçada — nomes inconsistentes, ausência de tipos, sem indicação clara de onde a regra de negócio vive — o LLM gera nova implementação.

O resultado: duplicação acelerada. Cada prompt pode virar uma nova cópia. E, como a IA é rápida, o time produz mais código e mais cópias por dia.

A boa notícia: a solução é a mesma de sempre. Modularização e tipagem rigorosa. A diferença é que agora o ROI é maior — código bem estruturado faz a IA trabalhar com você; código bagunçado faz a IA acelerar a degradação.

DRY vs WET — o princípio operacional

A engenharia clássica formaliza isso com DRY (Don't Repeat Yourself): cada pedaço de conhecimento tem uma representação única e autoritativa no sistema. Toda mudança na regra de negócio ocorre em um único lugar.

O oposto é o WET (Write Everything Twice) — cada uso reimplementa a lógica.

— Anti-padrão
WET
Write Everything Twice
  • ManutençãoAlta e arriscada (múltiplos pontos de falha)
  • BugsDifícil de localizar (erros espalhados, cópias ocultas)
  • IABaixa (cria redundâncias por falta de contexto)
  • AgilidadeReduzida pelo medo na base de código
  • ArquiteturaEntropia alta
+ Princípio
DRY
Don't Repeat Yourself
  • ManutençãoSimples (alteração centralizada)
  • BugsFacilitada (lógica única e autoritativa)
  • IAAlta (identifica e reutiliza módulos existentes)
  • AgilidadeElevada por familiaridade e segurança
  • Arquitetura"Casinhas" definidas
§ 5 Nuance

DRY tem uma nuance: aplicar de forma fanática (todo trecho de duas linhas vira uma função) gera abstração precoce, que é outro tipo de complexidade. A regra prática que funciona: três cópias = refatorar. Dois pode ser coincidência; três é padrão.

O que fazer agora
Plano operacional · 5 passos
  1. 1Rode Clone Detection no seu repo hoje. PMD/CPD, jscpd ou a plataforma SQA — escolha a que melhor se integra ao seu stack.
  2. 2Configure threshold operacional. Ponto de partida comum: alertar sobre blocos duplicados com 50+ tokens e 3+ cópias.
  3. 3Triagem por código quente. Não tente desduplicar tudo. Foque nas duplicações em código que muda com frequência (use git log --since para identificar).
  4. 4Refatoração coordenada. Para cada conjunto de cópias: definir versão autoritativa, criar testes, migrar usos um por um.
  5. 5Estabeleça baseline. Não introduza novas duplicações em PRs novos, mesmo aceitando o backlog atual.
Resumo · Pontos-chave
Cinco frases para levar embora.
  • Code Duplication é a replicação de comportamento em múltiplos pontos do sistema.
  • Diferentemente das outras métricas, o problema é espalhado, não agrupado. Sem epicentro.
  • Falha oculta é o risco real — você corrige uma cópia; o bug continua nas outras.
  • IA generativa acelerou o problema. Sem modularização e tipagem, LLMs produzem novas cópias em vez de reutilizar.
  • DRY como princípio operacional, sem fanatismo. Regra prática: três cópias = refatorar.
Próximo passo

Você leu cinco posts sobre métricas individuais. Cada uma com seu mecanismo, seu sintoma, sua remediação. O último post da série fecha a virada: por que olhar todas juntas importa mais do que olhar uma por vez — e como o método SQA estrutura essa visão integrada para diagnóstico cirúrgico.

Qualidade de código - Método SQA→

How Codurance can help

A Codurance acompanha times de engenharia que querem instrumentar a saúde do código sem virar gestores. Ajudamos Tech Leads e Staff Engineers a integrar Clone Detection em pipelines, definir estratégias de refatoração coordenada para conjuntos de cópias e estabelecer arquiteturas que mantêm a base limpa mesmo sob aceleração de IA generativa.

Se você quer aplicar essas práticas no seu time, entre em contato hoje.