Ao fazer uma revisão de código, há uma cena que encontro com frequência especial.
Você pesquisa para corrigir uma funcionalidade e encontra um código quase idêntico em três lugares. Corrige um, e os outros dois continuam como bugs.
A protagonista de hoje é DRY, o princípio que ataca esse problema diretamente. Ele anda lado a lado com o princípio KISS, que vimos da última vez.
DRY é a sigla de “Don’t Repeat Yourself”. É o princípio de não repetir o mesmo conhecimento dentro de um sistema.
Andy Hunt e Dave Thomas apresentaram esse conceito no livro de 1999 <The Pragmatic Programmer>, e a definição original é bastante precisa.
Todo conhecimento deve ter uma única representação inequívoca e autorizada dentro de um sistema.
A palavra importante aqui não é “código”, mas “conhecimento”. Esse é o ponto central da conversa de hoje.
Por que copiar e colar código é um problema?
Copiar e colar não é errado por si só. O problema acontece depois.
Se a mesma lógica existe em três lugares, quando os requisitos mudam você precisa encontrar e corrigir os três. Se deixar um passar, ele vira um bug.
// O cálculo do frete está espalhado por três arquivos
// Cart.swift
let fee = total >= 50000 ? 0 : 3000
// Checkout.swift
let shippingFee = totalPrice >= 50000 ? 0 : 3000
// OrderSummary.swift
let delivery = price >= 50000 ? 0 : 3000
E se um dia chegar o requisito de “reduzir o limite do frete grátis para 30 mil wones”? Você precisa encontrar os três arquivos. Como os termos de busca também são diferentes, algum deles certamente ficará para trás.
// Concentrar o conhecimento em um só lugar
// Shipping.swift
enum ShippingPolicy {
static let freeShippingThreshold = 50000
static let fee = 3000
static func shippingFee(for total: Int) -> Int {
total >= freeShippingThreshold ? 0 : fee
}
}
Agora, quando a política mudar, basta corrigir um único lugar. Isso é DRY.
A duplicação é de “conhecimento”, não de código
Mas é aqui que muita gente escorrega. Elas interpretam DRY como “junte todo código que parece semelhante”.
A duplicação mencionada pelo DRY não é a forma do código, mas o conhecimento — ou seja, a duplicação das regras de negócio.
Essa distinção é importante porque existe código que só se parece por acaso.
| Situação | É duplicação? |
|---|---|
| Lógica de cálculo do frete em três lugares | Duplicação real (mesmo conhecimento) |
| A validação do cadastro e a validação da inscrição em um evento são parecidas por acaso | Duplicação falsa (conhecimento diferente) |
| A constante 3000 aparece separadamente no frete e no limite para acumular pontos | Duplicação falsa (significados diferentes) |
A validação do cadastro e a validação da inscrição em eventos parecem iguais porque atualmente ambas exigem “nome obrigatório e telefone com 11 dígitos”, mas as duas regras mudam por motivos diferentes. Se você as unir, uma mudança nas regras do evento pode quebrar o cadastro.
Uma abstração precipitada custa mais que a duplicação
Por isso, nas comunidades de desenvolvimento, é comum ouvir: “prefer duplication over the wrong abstraction”. A frase é de Sandy Metz, uma conhecida desenvolvedora Ruby.
Quando você força a união de dois trechos de código que apenas parecem semelhantes, acontece o seguinte.
- Criar uma função comum
- O requisito de um lado muda, então você adiciona um parâmetro de opção
- O outro lado também muda, então você adiciona uma ramificação if
- De repente, vira uma função com cinco parâmetros que ninguém entende
Nesse ponto, teria sido melhor manter duas cópias do código.
Por isso, no trabalho, muita gente usa a Regra de Três. Quando um padrão aparece duas vezes, apenas observe; quando aparecer pela terceira vez, faça a abstração. Depois de cerca de três repetições, fica claro se é realmente o mesmo conhecimento ou apenas coincidência.
Meu critério de decisão
Quando encontro uma duplicação, faço uma pergunta.
Esses dois códigos mudam pelo mesmo motivo?
Se mudam pelo mesmo motivo, é duplicação real, então eu uno os dois. Se mudam por motivos diferentes, deixo como estão, por mais parecidos que sejam.
Conclusão de hoje
Em resumo, o princípio DRY se resume a isto.
- A unidade da duplicação é o conhecimento (as regras de negócio), não a aparência do código.
- Una apenas o código que muda pelo mesmo motivo. Deixe como está o código que só parece semelhante por acaso.
- Se não tiver certeza, use a Regra de Três. Não é tarde demais para abstrair na terceira repetição.
Se KISS significa “mantenha simples”, DRY significa “mantenha o conhecimento em um só lugar”. No fim, ambos falam sobre reduzir o custo de mudança.
Você provavelmente consegue lembrar de uma lógica que aparece em três lugares sempre que a pesquisa é feita. Essa é a candidata à refatoração de hoje.

