Introdução
A visão original de Kay para OOP não era "objetos com dados públicos que outros manipulam", era objetos que trocam mensagens e decidem sozinhos o que fazer com elas.
é Tell dont ask é basicasmente um resgate dessa ideia original, porquer com o tempo muita gente passou a usar OOP como “structs com getters e setters”, pedendo o encapsulamento de verdade.
Ideia Central
Exemplo do Cliente e Carteira
Ask
Eu PERGUNTO o saldo, e EU decido o que fazer com ele
if (cliente.carteira.saldo >= 50) {
cliente.carteira.saldo -= 50;
} else {
console.log("saldo insuficiente");
}
Tell
Eu DIGO pro cliente pagar, e ELE decide o que faze
// "Tell" — eu DIGO pro cliente pagar, e ELE decide o que fazer
cliente.pagar(50);
class Cliente {
carteira: Carteira;
pagar(valor: number) {
if (this.carteira.saldo < valor) {
throw new Error("saldo insuficiente");
}
this.carteira.saldo -= valor;
}
}
Repare a diferença de responsabilidade:
- No "Ask", quem chama o código precisa saber a regra ("se o saldo for menor, não pode pagar") e tomar a decisão sozinho.
- No "Tell", o próprio objeto conhece sua regra e decide por dentro. Quem chama só diz o que quer que aconteça.
Por que "perguntar" é perigoso
Pensa no "Ask" espalhado pelo sistema: toda tela, todo botão, todo endpoint que cobra do cliente vai ter que copiar essa mesma verificação de saldo:
if (cliente.carteira.saldo >= valorDoCarrinho) { ... }
if (cliente.carteira.saldo >= valorDaAssinatura) { ... }
if (cliente.carteira.saldo >= valorDoBoleto) { ... }
Se um dia a regra mudar (por exemplo, "clientes VIP podem ficar com saldo negativo até -R$100"), você precisa caçar todos esses lugares e mudar um por um. É praticamente garantido que algum lugar vai ser esquecido — e aí seu sistema tem um bug de regra de negócio inconsistente.
Com "Tell", a regra mora em um lugar só (Cliente.pagar). Mudar uma vez, resolve todo o sistema.
Como isso conecta com Law of Demeter
Os dois princípios andam juntos, mas resolvem problemas ligeiramente diferentes:
-
Law of Demeter: não atravesse a estrutura interna de outros objetos (
a.b.c). - Tell, Don't Ask: não extraia dados de um objeto pra decidir algo fora dele — mande o objeto decidir.
Na prática, quando você aplica bem "Tell, Don't Ask", quase sempre acaba respeitando Law of Demeter de graça — porque você para de precisar alcançar o carteira.saldo de fora.
O sinal de alerta pra reconhecer
Pergunte-se, olhando pro código:
"Estou pegando um dado de dentro de um objeto só pra, logo em seguida, tomar uma decisão (
if) ou fazer uma conta com esse dado?"
Se sim, é sinal de "Ask". Pergunte então: "quem deveria saber essa regra: eu (quem está chamando) ou o objeto dono do dado?" Quase sempre é o objeto dono.
// Sinal de alerta: pegou o dado (idade) e decidiu por fora
if (usuario.idade>= 18) { liberarCompra(); }
// Melhor: quem sabe a regra de maioridade é o próprio usuário
if (usuario.podeComprar()) { liberarCompra(); }
Quando NÃO aplicar ao pé da letra
- Código que só exibe dados (uma tela mostrando o saldo do cliente) precisa "perguntar" — não tem decisão de negócio envolvida, só exibição. Tell, Don't Ask é sobre decisões e comportamento, não sobre leitura pura de dados para exibir.
- Structs/DTOs (objetos que só carregam dados entre camadas, tipo resposta de API) não precisam desse princípio — eles não têm comportamento por definição.
Top comments (0)