DRY, KISS e YAGNI: os princípios que todo dev deve conhecer
1. Introdução aos três pilares da simplicidade
1.1. O que são DRY, KISS e YAGNI e por que são fundamentais na Arquitetura de Software
DRY (Don't Repeat Yourself), KISS (Keep It Simple, Stupid) e YAGNI (You Ain't Gonna Need It) formam a tríade de princípios que orientam decisões arquiteturais rumo à simplicidade e manutenibilidade. DRY combate a duplicação de conhecimento, KISS defende soluções diretas e YAGNI previne implementações prematuras. Juntos, eles atuam como filtros contra a complexidade acidental — aquela que introduzimos sem necessidade real.
1.2. A relação entre esses princípios e a redução de complexidade acidental
Complexidade acidental surge quando a solução técnica é mais intrincada que o problema de negócio. DRY reduz a dispersão de lógica, KISS elimina adornos desnecessários e YAGNI corta funcionalidades especulativas. Um sistema que respeita esses três princípios tende a ter menor custo de mudança e maior previsibilidade.
1.3. Como eles se complementam (e às vezes se contradizem) no design de sistemas
Embora complementares, esses princípios podem entrar em conflito. DRY pode levar a abstrações complexas que violam KISS. YAGNI pode sugerir duplicação temporária que contradiz DRY. O equilíbrio exige análise contextual: domínio, frequência de mudança e maturidade do time determinam qual princípio deve prevalecer em cada decisão.
2. DRY (Don't Repeat Yourself) – A luta contra a duplicação
2.1. Definição formal: cada conhecimento deve ter uma representação única, não ambígua e autoritativa
DRY afirma que toda peça de conhecimento deve ter uma representação única dentro do sistema. Isso não se limita a código — inclui documentação, configurações e regras de negócio. Violações geram inconsistências: corrigir um bug em um local e esquecer outro é a consequência mais comum.
2.2. Armadilhas comuns: duplicação acidental vs. duplicação intencional
Nem toda repetição é violação de DRY. Duplicação acidental ocorre quando código similar surge por coincidência, mas representa conceitos diferentes. Duplicação intencional pode ser válida quando contextos de negócio distintos exigem evolução independente.
// Duplicação acidental (candidata a DRY)
function calcularImpostoVenda(valor) { return valor * 0.1; }
function calcularTaxaServico(valor) { return valor * 0.1; }
// Duplicação intencional (contextos diferentes)
function calcularImpostoVenda(valor) { return valor * 0.1; }
function calcularTaxaServico(valor) { return valor * 0.05; } // regra diferente
2.3. Aplicação arquitetural: extração de serviços, bibliotecas compartilhadas e abstrações mal planejadas
Em arquitetura, DRY justifica serviços compartilhados, bibliotecas internas e módulos reutilizáveis. Porém, extrair um serviço comum antes de existirem três consumidores distintos é abstração prematura. O custo de acoplamento introduzido pode superar o benefício da eliminação de duplicação.
3. KISS (Keep It Simple, Stupid) – A simplicidade como meta de design
3.1. O princípio da navalha de Occam aplicado a componentes e módulos
KISS aplica a navalha de Occam à engenharia de software: entre duas soluções equivalentes, a mais simples é preferível. Componentes com responsabilidade única, interfaces enxutas e fluxos lineares são manifestações desse princípio. Um módulo que faz uma coisa bem é mais fácil de testar, depurar e modificar.
3.2. Como evitar over-engineering: soluções simples vencem soluções genéricas prematuras
Over-engineering é o resultado de antecipar requisitos que nunca chegam. Um sistema de plugins para três variações de notificação quando apenas e-mail é necessário é um exemplo clássico. A simplicidade deve ser a default, e a complexidade, uma concessão justificada.
// Solução KISS: direta e específica
function enviarEmail(destinatario, assunto, corpo) {
// implementação direta
}
// Solução over-engineered: genérica e complexa
function notificar(usuario, tipo, template, canais) {
// fábrica de notificações, roteamento, fallback
}
3.3. Trade-offs entre simplicidade e flexibilidade futura
Monolitos são mais simples que microsserviços, mas menos flexíveis. A decisão depende do ciclo de vida do projeto: um MVP deve priorizar KISS; um sistema maduro com times independentes pode justificar a complexidade adicional. O trade-off é sempre contextual.
4. YAGNI (You Ain't Gonna Need It) – O custo da antecipação
4.1. Definição: nunca implementar funcionalidades antes de serem realmente necessárias
YAGNI ensina que implementar algo "por precaução" gera custo imediato (desenvolvimento, teste, manutenção) com benefício incerto. Funcionalidades especulativas tendem a nunca ser usadas ou, quando usadas, precisam ser refeitas porque os requisitos mudaram.
4.2. O paradoxo da previsibilidade: quando YAGNI colide com requisitos não funcionais
YAGNI não significa ignorar requisitos arquiteturais óbvios. Logging, tratamento de erros e segurança não são "funcionalidades" — são requisitos não funcionais essenciais. O paradoxo surge quando a antecipação é necessária para viabilidade técnica futura (ex.: escalabilidade horizontal desde o início).
4.3. Estratégias para prototipação rápida e entrega incremental
Aplicar YAGNI não significa ausência de planejamento. Use prototipação rápida para validar hipóteses, entregue incrementos funcionais e refatore quando a necessidade real surgir. A arquitetura deve permitir evolução sem reescritas completas.
// YAGNI violado: cache desnecessário
function buscarUsuario(id) {
if (cache.existe(id)) return cache.obter(id);
var usuario = banco.buscar(id);
cache.armazenar(id, usuario);
return usuario;
}
// YAGNI respeitado: implementação direta
function buscarUsuario(id) {
return banco.buscar(id);
}
5. Tensões e sinergias entre DRY, KISS e YAGNI
5.1. DRY vs. KISS: quando abstrair demais para evitar repetição torna o sistema mais complexo
Uma abstração que unifica três casos similares, mas requer parâmetros de configuração complexos e condicionais internos, viola KISS em nome de DRY. A simplicidade do consumidor (chamada única) esconde complexidade do provedor.
5.2. YAGNI vs. DRY: como a duplicação temporária pode ser mais simples que uma abstração prematura
Duplicar código em dois contextos que podem divergir é melhor que criar uma abstração genérica prematura. Quando os contextos convergirem (terceira ocorrência), a abstração natural será mais adequada.
5.3. Critérios de decisão: contexto do domínio, frequência de mudança e maturidade do time
Três perguntas ajudam a decidir: (1) Este código representa o mesmo conceito de negócio? (2) Com que frequência muda? (3) O time consegue manter a abstração? Respostas negativas favorecem duplicação temporária (YAGNI + KISS) sobre DRY.
6. Aplicação prática na Arquitetura de Software
6.1. Exemplo em design de APIs: evitar duplicação de lógica de validação sem criar abstrações frágeis
// Sem DRY: validação duplicada
POST /usuario { validarEmail(email); validarCPF(cpf); }
POST /pedido { validarEmail(email); validarCPF(cpf); }
// Com DRY: validação centralizada, mas simples
POST /usuario { validarDadosPessoaFisica(dados); }
POST /pedido { validarDadosPessoaFisica(dados); }
6.2. Exemplo em camadas de serviço: quando extrair um serviço comum
Extraia um serviço comum apenas quando houver três consumidores com requisitos idênticos. Até lá, duplicação controlada (com documentação explícita) é mais KISS e YAGNI.
6.3. Exemplo em bancos de dados: normalização (DRY) vs. desnormalização por performance
Normalização é DRY aplicado a dados. Desnormalização sacrifica DRY por performance (KISS para consultas). A decisão depende do padrão de acesso: se leituras dominam, desnormalizar pode ser a escolha KISS.
7. Antipadrões e erros comuns
7.1. O "DRY extremo": abstrações genéricas que escondem complexidade
Uma classe RepositorioGenerico<T> com reflexão, queries dinâmicas e tratamento de exceções genérico é DRY no código, mas KISS violado. Cada consumidor paga o custo cognitivo da complexidade.
7.2. O "YAGNI míope": ignorar requisitos arquiteturais óbvios
Não implementar logging, monitoramento ou tratamento de erros padronizado "porque YAGNI" é negligência. Esses não são funcionalidades especulativas — são infraestrutura necessária.
7.3. O "KISS ingênuo": soluções simplistas que geram dívida técnica acumulada
Evitar toda abstração leva a código procedural, funções gigantes e ausência de separação de concerns. KISS não significa ausência de design — significa design direto e sem complicação desnecessária.
8. Conclusão: como equilibrar os três princípios no dia a dia
8.1. Checklist prático para decisões arquiteturais
- A duplicação é acidental ou intencional? (DRY)
- A solução mais simples resolve o problema atual? (KISS)
- Essa funcionalidade é necessária agora? (YAGNI)
- Qual o custo de mudança futura versus custo imediato?
8.2. A importância do contexto: domínio, time e ciclo de vida
Projetos maduros com times experientes toleram mais abstrações (DRY). Startups em fase inicial devem priorizar KISS e YAGNI. Domínios complexos exigem mais DRY que domínios simples.
8.3. Relação com outros princípios
DRY, KISS e YAGNI conversam diretamente com SOLID (especialmente Single Responsibility e Interface Segregation), Lei de Demeter (baixo acoplamento) e coesão. Juntos, formam a base para decisões arquiteturais pragmáticas e sustentáveis.
O equilíbrio entre esses três princípios não é fórmula matemática — é habilidade adquirida com prática, reflexão e feedback contínuo. A boa arquitetura não é a mais elegante teoricamente, mas a que resolve o problema real com o menor custo de manutenção ao longo do tempo.
Referências
- The DRY Principle: Don't Repeat Yourself - The Pragmatic Programmer — Referência clássica que define o princípio DRY e suas aplicações práticas em arquitetura de software.
- Keep It Simple, Stupid (KISS) - Principles of Software Design — Artigo técnico que explora o princípio KISS com exemplos de design de sistemas e armadilhas comuns.
- You Ain't Gonna Need It (YAGNI) - Extreme Programming — Definição oficial do YAGNI no contexto de Extreme Programming, com discussão sobre custo da antecipação.
- DRY, KISS, YAGNI: A Practical Guide - Martin Fowler's Bliki — Artigo de Martin Fowler sobre YAGNI e sua relação com design evolucionário e refatoração.
- The Relationship Between DRY, KISS and YAGNI - Codecademy Blog — Tutorial prático que demonstra conflitos e sinergias entre os três princípios com exemplos de código.
- Occam's Razor in Software Architecture - O'Reilly — Capítulo sobre aplicação da navalha de Occam (KISS) em decisões arquiteturais, incluindo trade-offs com DRY e YAGNI.