DEV Community

Yuri Peixinho
Yuri Peixinho

Posted on

TDA (Tell Don't Ask)

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");
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode
class Cliente {
  carteira: Carteira;

  pagar(valor: number) {
    if (this.carteira.saldo < valor) {
      throw new Error("saldo insuficiente");
    }
    this.carteira.saldo -= valor;
  }
}
Enter fullscreen mode Exit fullscreen mode

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) { ... }
Enter fullscreen mode Exit fullscreen mode

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(); }
Enter fullscreen mode Exit fullscreen mode

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)