"YAGNI explicado: você não vai precisar disso"
Entenda o princípio You Aren't Gonna Need It, como ele combate o over-engineering, equilibra-se com DRY e SOLID e por que construir só o necessário hoje deixa o software mais ágil.

YAGNI é um daqueles princípios que parecem óbvios até você se pegar construindo uma camada de abstração para um requisito que ninguém pediu. A sigla resume uma disciplina difícil: resistir à tentação de antecipar o futuro no código de hoje. Neste artigo você vai entender de onde vem o YAGNI, por que ele economiza tempo e dinheiro, como ele se relaciona com outros princípios de design e como aplicá-lo sem usá-lo como desculpa para escrever código descuidado. No fim, há uma seção de perguntas frequentes para fechar as dúvidas mais comuns.
A tentação de "preparar o terreno" é especialmente forte para quem está construindo software com a ajuda de IA: pedir a um assistente que gere um sistema "flexível e extensível" quase sempre produz mais estrutura do que o problema exige. Entender YAGNI é, hoje, parte essencial de saber revisar o que a IA entrega.
O que é YAGNI
YAGNI é a sigla de You Aren't Gonna Need It — "você não vai precisar disso". O princípio surgiu na cultura do Extreme Programming, atribuído a Ron Jeffries e aos primeiros praticantes do XP, e diz, de forma direta: não implemente algo até que seja de fato necessário. Nada de adicionar funcionalidade, parâmetro de configuração ou ponto de extensão "porque um dia pode ser útil".
A lógica é simples. Quando você constrói algo para uma necessidade futura imaginada, três coisas podem acontecer, e duas são ruins:
- A necessidade nunca chega, e você desperdiçou esforço mantendo código morto.
- A necessidade chega diferente do que você imaginou, e a generalização vira um estorvo a ser desfeito.
- A necessidade chega exatamente como você previu — o caso raro que dá razão à aposta.
Como apostar certo é exceção, o saldo médio do "preparar para o futuro" é negativo. Repare que mesmo no melhor cenário (caso 3) o ganho é modesto: você economizou o tempo de adicionar a feature depois, mas pagou o custo de carregá-la durante todo o intervalo. Nos outros dois cenários, o prejuízo é claro e às vezes severo, porque desfazer uma abstração errada custa mais do que nunca tê-la criado.
YAGNI é, no fundo, uma aposta estatística: na dúvida, escolha não construir, porque o valor esperado de adiar é maior que o de antecipar.
A diferença entre código necessário e código especulativo
A distinção central do YAGNI é entre o que o sistema precisa agora e o que ele talvez precise. Código especulativo carrega custos que muitas vezes ignoramos:
- Custo de construção: o tempo gasto criando o que não era preciso.
- Custo de manutenção: cada linha extra precisa ser lida, testada e compreendida por anos.
- Custo de atraso: enquanto você construía a abstração hipotética, a entrega real ficou esperando.
- Custo de carregar: a complexidade adicional torna todo o resto mais difícil de mudar.
Martin Fowler decompõe esse desperdício em quatro categorias: o custo de construir a feature que não era necessária; o custo de atraso das features que de fato importavam; o custo de carregar a complexidade extra enquanto a feature espera; e o custo de reparar, caso você precise desfazer a abstração errada (Fowler, 2015). Cada generalização não usada é peso morto que torna o sistema mais lento para evoluir.
Há ainda um custo invisível: o custo cognitivo. Toda pessoa que ler o código no futuro precisará entender por que aquela hierarquia de classes existe, por que há três parâmetros que sempre recebem o mesmo valor, por que existe um ponto de extensão sem nenhuma extensão. Esse esforço de compreensão se repete a cada nova pessoa que toca o arquivo — multiplicando o desperdício original.
YAGNI e o combate ao over-engineering
Over-engineering é a doença que o YAGNI trata. Acontece quando resolvemos problemas que ainda não existem: o sistema de plugins para um app que tem um cliente, a camada de cache para uma tabela com cem linhas, o parâmetro genérico que só é chamado de um jeito.
Frederick Brooks, em seu ensaio clássico No Silver Bullet, distingue a complexidade essencial — inerente ao problema que estamos resolvendo — da complexidade acidental, que nós mesmos introduzimos (Brooks, 1987). Over-engineering é a forma mais pura de complexidade acidental: estrutura criada não pelo problema, mas pela nossa ansiedade em relação ao futuro.
YAGNI mantém o foco na complexidade essencial. Você resolve o problema que tem na mão, com a estrutura mínima que ele exige. Isso conversa diretamente com o KISS: o princípio Keep It Simple, Stupid no desenvolvimento de software: manter simples é, em grande parte, não adicionar o que não é necessário.
Vale notar a sutil diferença de foco entre os dois princípios. KISS fala sobre como você escreve o que escreve — prefira a solução mais direta. YAGNI fala sobre se você deveria escrever aquilo — não escreva o que ninguém precisa ainda. Um trata da simplicidade da solução; o outro, da existência da solução. Juntos, formam a espinha dorsal do design enxuto.
Um exemplo concreto
Imagine que você precisa enviar um e-mail de boas-vindas quando um usuário se cadastra. O requisito é exatamente esse — um e-mail.
A versão "preparada para o futuro" pode parecer assim:
interface CanalNotificacao {
enviar(destinatario: string, mensagem: string): Promise<void>;
}
class EmailChannel implements CanalNotificacao { /* ... */ }
class SmsChannel implements CanalNotificacao { /* ... */ }
class PushChannel implements CanalNotificacao { /* ... */ }
class WhatsappChannel implements CanalNotificacao { /* ... */ }
class GerenciadorNotificacoes {
constructor(private canais: CanalNotificacao[]) {}
async notificar(usuario: Usuario, tipo: string) {
// roteamento por preferência, fallback, retry...
}
}Quatro canais, um gerenciador, roteamento, fallback — para enviar um e-mail. SMS, push e WhatsApp foram construídos para um futuro que talvez nunca chegue, e cada um precisa ser mantido e testado desde já.
A versão YAGNI faz só o pedido:
async function enviarBoasVindas(email: string, nome: string) {
await servicoEmail.enviar({
para: email,
assunto: "Bem-vindo!",
corpo: `Olá, ${nome}! Que bom ter você aqui.`,
});
}Direta, fácil de ler, fácil de mudar. Se um dia o requisito de SMS realmente aparecer, você introduz a abstração naquele momento — com informação real sobre como os canais precisam se comportar, em vez de um palpite. Esse momento de reorganizar a estrutura sob demanda é, justamente, O que é refatoração e quando aplicar.
Repare na assimetria: a versão YAGNI não fecha portas. Quando o SMS chegar, refatorar de uma função simples para uma interface custa pouco — você extrai a abstração de duas implementações concretas que já entende. O contrário não é verdade: desmontar o gerenciador de quatro canais quando descobrir que a empresa só vai usar e-mail por mais dois anos é trabalho puro de demolição.
O caso do parâmetro "só por garantia"
Um exemplo ainda mais sorrateiro de over-engineering é o parâmetro especulativo. Veja esta função:
def gerar_relatorio(usuario, formato="pdf", incluir_graficos=True,
idioma="pt-BR", compactar=False, marca_dagua=None):
# ... mas o sistema só chama gerar_relatorio(usuario)
...Cinco parâmetros opcionais, e na prática todas as chamadas usam os valores padrão. Cada parâmetro é uma promessa de comportamento que precisa ser testada, documentada e mantida — para flexibilidade que ninguém usa. A versão YAGNI assume apenas o que o presente exige:
def gerar_relatorio(usuario):
# gera o PDF em pt-BR com gráficos, que é o único caso real
...Quando surgir o pedido real de um relatório em inglês ou sem gráficos, você adiciona o parâmetro com a certeza de que ele será usado — e com um exemplo concreto para guiar o design.
YAGNI não é desculpa para código ruim
Aqui está o mal-entendido mais perigoso. YAGNI diz para não adicionar funcionalidade especulativa — não para escrever código desleixado, pular testes ou ignorar bons nomes. Construir só o necessário e construir bem são coisas independentes.
Algumas distinções úteis:
- YAGNI x SOLID: você não precisa de cinco camadas de abstração hoje, mas o código que existe ainda deve respeitar princípios sólidos de design. Os O que é SOLID? Os 5 princípios do design orientado a objetos ajudam a estruturar bem o que de fato existe, sem te obrigar a antecipar o que não existe.
- YAGNI x DRY: tolerar uma pequena duplicação até entender o padrão é YAGNI saudável; mas quando o conhecimento duplicado é claro, o O que é DRY? Não se repita e elimine duplicação de código deve ser aplicado. Os dois princípios se equilibram: não abstraia cedo demais (YAGNI), mas não conviva com duplicação real de conhecimento (DRY).
- YAGNI x design patterns: aplicar um padrão de projeto "para garantir flexibilidade" sem necessidade concreta é over-engineering. Conheça os Design Patterns essenciais que todo dev deveria conhecer, mas use-os quando o problema pedir, não como decoração.
A síntese é esta: YAGNI restringe o que você constrói, não a qualidade com que constrói. Um sistema YAGNI ideal faz pouquíssimas coisas, mas faz cada uma delas com clareza, testes e nomes honestos.
O equilíbrio difícil: YAGNI versus abstração prematura
O trade-off mais delicado do dia a dia é decidir o momento certo de abstrair. Abstrair cedo demais é over-engineering. Abstrair tarde demais é conviver com duplicação que esconde um conceito importante. Onde fica a fronteira?
A heurística mais conhecida vem de Sandi Metz: "duplicação é muito mais barata do que a abstração errada" (Metz, 2016). A consequência prática é contraintuitiva — quando estiver em dúvida, prefira duplicar e espere. A duplicação fica visível, incomoda e ensina: com duas ou três cópias na sua frente, você enxerga qual parte realmente varia e qual é estável. Aí, e só aí, a abstração certa se revela quase sozinha.
A "regra de três" de Martin Fowler captura o mesmo instinto: você tolera a primeira ocorrência, suporta a segunda com um leve incômodo e, na terceira, refatora para remover a duplicação (Fowler, 1999). Antes da terceira, você simplesmente não tem informação suficiente sobre o padrão para abstraí-lo bem.
Por que a abstração errada é tão cara? Porque ela acopla coisas que pareciam iguais mas não eram. Quando o terceiro caso chega e não encaixa, o desenvolvedor seguinte tende a adicionar um parâmetro condicional em vez de desfazer a abstração — e a cada novo caso, mais um if. O resultado é uma função genérica cheia de bandeiras que serve a todos mal. Era melhor ter três funções simples e separadas.
// Abstração prematura que apodrece:
function processar(item, tipo, comDesconto, ehVip, modoLegado) {
if (tipo === "A") { /* ... */ }
else if (tipo === "B" && ehVip) { /* ... */ }
else if (modoLegado) { /* ... */ }
// cada novo caso adiciona mais uma flag
}
// Versus duplicação honesta que se mantém clara:
function processarPedidoPadrao(item) { /* ... */ }
function processarPedidoVip(item) { /* ... */ }A duplicação à direita parece "pior" porque repete linhas. Mas é honesta: cada função diz exatamente o que faz, e mudar uma não arrisca quebrar a outra. Esse é o YAGNI no nível da abstração — não generalize antes de a generalização estar madura.
Como praticar YAGNI
Algumas perguntas ajudam a manter a disciplina no dia a dia:
- "Esse requisito já existe?" Se a resposta é "não, mas pode aparecer", é candidato a ser cortado.
- "Quem pediu isso?" Se ninguém pediu e é uma antecipação sua, desconfie.
- "Quanto custa adicionar depois?" Se for barato adicionar quando a necessidade chegar, adiar é quase sempre a escolha certa.
- "Estou prevendo o futuro ou respondendo ao presente?" Hunt e Thomas defendem código fácil de mudar justamente para que você possa adiar decisões com tranquilidade (Hunt e Thomas, 1999) — código flexível e simples é o que permite dizer "depois" sem medo.
A última pergunta revela a relação saudável entre YAGNI e bom design: você adia features não por preguiça, mas porque construiu um código tão limpo e desacoplado que adicionar a feature mais tarde será fácil. YAGNI funciona melhor em cima de um código bem cuidado.
Um passo a passo para revisar uma proposta de implementação
Quando você (ou um assistente de IA)) propõe uma estrutura, vale rodar este filtro antes de aceitar:
- Liste o requisito real, em uma frase. Se não couber em uma frase, talvez existam vários requisitos misturados — separe-os.
- Marque cada peça de código como "exigida" ou "antecipada". Toda interface, classe abstrata, parâmetro opcional e ponto de extensão entra em julgamento.
- Para cada peça "antecipada", pergunte o custo de adiar. Se adiar é barato (um refactor localizado), corte agora.
- Para o que sobrou, exija um caso de uso presente e nomeado. "Pode ser que precisemos" não conta; "a tela X já chama isso" conta.
- Garanta que o que ficou está limpo. YAGNI cortou o excesso; agora aplique testes, nomes e O que é refatoração e quando aplicar ao núcleo que restou.
Esse ritual transforma YAGNI de uma intuição vaga em uma checagem repetível — especialmente útil ao revisar código gerado por IA, que tende a entregar generosamente mais estrutura do que o pedido.
Erros comuns ao aplicar YAGNI
Mesmo quem conhece o princípio escorrega. Os deslizes mais frequentes:
- Confundir YAGNI com "não pensar no design". YAGNI corta features especulativas, não reflexão. Você ainda precisa pensar na arquitetura — só não precisa implementá-la inteira hoje.
- Usar YAGNI para justificar gambiarra. "Não vou tratar esse erro porque YAGNI" é abuso do princípio. Tratar um erro que já pode acontecer é necessidade presente, não especulação.
- Aplicar YAGNI a decisões caras de reverter. Escolher o modelo de dados ou a fronteira entre serviços não é o tipo de coisa que se "adiciona depois" barato. YAGNI brilha no que é barato de mudar.
- Ignorar requisitos não funcionais conhecidos. Segurança, privacidade e observabilidade quase nunca são "adicionáveis depois" sem dor. Eles são necessidade presente assim que você tem usuários reais.
- Confundir generalização com flexibilidade. Código simples e bem fatorado já é flexível — você muda quando precisa. Generalizar antecipadamente não é flexibilidade, é peso.
Quando YAGNI não se aplica
Como todo princípio, YAGNI tem limites. Há decisões caras de reverter mais tarde — e essas merecem reflexão antecipada:
- Escolhas estruturais difíceis de mudar, como o modelo de dados central ou a fronteira entre serviços.
- Requisitos não funcionais conhecidos, como segurança e privacidade, que não devem ser "adicionados depois".
- Pontos de extensão exigidos por um requisito real e iminente, já no backlog priorizado.
A regra de bolso: aplique YAGNI agressivamente a tudo que for barato de adicionar depois, e pense com cuidado naquilo que será caro de mudar. A maior parte do código cai na primeira categoria.
Uma forma útil de pensar nisso é separar decisões reversíveis de irreversíveis. Para o reversível, YAGNI é quase sempre a resposta: faça o mínimo, e mude quando precisar, porque mudar é barato. Para o irreversível, vale investir mais análise antecipada, porque o custo de errar é alto. O erro comum é tratar tudo como irreversível — e assim justificar over-engineering em todo canto. Na prática, a maioria das decisões de código é reversível, e é por isso que YAGNI ganha tantas vezes.
YAGNI no desenvolvimento com IA
Quem constrói apps com assistentes de IA encontra um amplificador de over-engineering. Peça "um sistema de notificações" e o modelo entregará interfaces, fábricas e canais que você não pediu — porque foi treinado em código que tende a ser genérico e "completo". O resultado é tecnicamente impressionante e funcionalmente excessivo.
A defesa é fazer do YAGNI uma instrução explícita e um critério de revisão:
- Peça o mínimo. Em vez de "crie um sistema de notificações", diga "envie um e-mail de boas-vindas neste cadastro". Quanto mais específico o pedido, menos especulação.
- Revise contra o requisito. Rode o passo a passo da seção anterior sobre o que a IA gerou: cada abstração tem um caso de uso presente?
- Mande simplificar. "Remova o que não é usado por este requisito" costuma encolher a entrega à metade sem perder nada real.
YAGNI deixa de ser só um princípio de quem escreve código e passa a ser um princípio de quem revisa código — incluindo o que a máquina produz. Saber identificar e cortar o excesso é uma das habilidades mais valiosas do desenvolvedor moderno.
Perguntas frequentes
YAGNI significa que não devo planejar nada? Não. YAGNI corta a implementação especulativa, não o pensamento. Você ainda deve refletir sobre arquitetura, antecipar riscos e desenhar fronteiras — só não constrói código para necessidades que ainda não existem. Planejar é barato; implementar o que não se usa é caro.
E quando eu tenho quase certeza de que a feature vai ser pedida? "Quase certeza" sobre o futuro é exatamente o que o histórico mostra ser pouco confiável. Mesmo certo sobre o se, é difícil acertar o como. Se adicionar a feature depois for barato, espere — você a construirá com informação real. Reserve a antecipação para o que é caro de mudar depois.
YAGNI não entra em conflito com DRY? Eles se equilibram, não se contradizem. YAGNI diz para não abstrair cedo demais; DRY diz para não conviver com duplicação de conhecimento. A síntese, de Sandi Metz, é "prefira duplicação à abstração errada" — ou seja, tolere a repetição até o padrão ficar claro, e então aplique DRY.
Como explico YAGNI para um time que adora "deixar pronto para o futuro"? Mostre o custo concreto: features especulativas atrasam entregas reais e adicionam complexidade que todos precisam manter. Use a métrica de Fowler — custo de construir, de atrasar, de carregar e de reparar — para tornar o desperdício visível. Combine com a regra de três para dar um critério objetivo de quando abstrair.
YAGNI vale para testes também? Não da mesma forma. Testes do comportamento que já existe são necessidade presente, não especulação. O que YAGNI desencoraja é escrever testes para funcionalidades que você ainda não construiu por especulação — porque elas não deveriam existir ainda.
Conclusão
YAGNI é uma defesa contra a nossa própria ansiedade. Programadores adoram resolver problemas, e isso nos leva a resolver problemas que ainda não temos — gastando tempo, adicionando complexidade acidental e atrasando o que importa. O princípio nos lembra de uma verdade incômoda: a maioria das nossas previsões sobre o futuro está errada, então construir para elas é, no agregado, prejuízo.
Adotar YAGNI não significa programar mal nem ignorar design. Significa direcionar o esforço para o que é necessário agora, manter esse necessário limpo e flexível, equilibrar a tolerância à duplicação com a aplicação de DRY no momento certo, e confiar que, quando o futuro chegar de verdade, você o atenderá com informação real em mãos. No mundo do desenvolvimento assistido por IA, essa disciplina vira também a arte de revisar e enxugar o que a máquina gera generosamente demais. Construa o presente com cuidado — e deixe o futuro pagar pela própria complexidade.
Referências
- Andrew Hunt, David Thomas (1999). The Pragmatic Programmer: From Journeyman to Master. Addison-Wesley.
- Frederick P. Brooks (1987). No Silver Bullet: Essence and Accidents of Software Engineering. IEEE Computer.
- Martin Fowler (2015). Yagni. martinfowler.com.
- Martin Fowler (1999). Refactoring: Improving the Design of Existing Code. Addison-Wesley.
- Sandi Metz (2016). The Wrong Abstraction. sandimetz.com.


