Скажи не спрашивай

В объектно-ориентированном программировании TDA (Tell Don’t Ask) означает указание объекту выполнить действие, а не запрашивать информацию и выполнять действия от имени объекта.

Одна из фундаментальных идей ООП — связать воедино поведение и данные. Когда класс обслуживания запрашивает информацию у объекта и выполняет над ним операции, это приводит к разделению поведения и данных, при этом поведение реализуется в классе обслуживания, а данные остаются в объекте.

Поведение и данные лучше всего тесно связаны, потому что они обычно меняются вместе и по одной и той же причине. Это также отделяет объект от клиента, позволяя ему сосредоточиться на выполнении операций и поддержании достоверности своего состояния. Между тем, клиент может обрабатывать логику приложения, взаимодействие между объектами и связь с другими уровнями. Такое разделение задач обеспечивает удобство сопровождения системы в долгосрочной перспективе.

Пример

Давайте подумаем о реальном сценарии. В ресторанах официанты обычно говорят клиентам оплачивать счета, а не просят предъявить их кошельки и берут у них наличные. В последнем случае клиент не может быть уверен, сколько наличных было снято с его кошелька. Это может привести к проблемам, потому что клиент несет ответственность за управление деньгами в своем кошельке.

Реализация запроса кошелька будет следующей.

type Wallet = { cash: number };

class Customer {
  private wallet: Wallet = { cash: 100 };

  public getWallet(): Wallet {
    return this.wallet;
  }

  public setWallect(wallet: Wallet): void {
    this.wallet = wallet;
  }
}

class PayBillService {
  public handle(paymentAmount: number): void {
    const customer = new Customer();
    const wallet: Wallet = { cash: customer.getWallet().cash - paymentAmount };
    customer.setWallect(wallet);
  }
}

new PayBillService().handle(10);

Реализация сообщения клиенту об оплате счета будет следующей.

type Wallet = { cash: number };

class Customer {
  private wallet: Wallet = { cash: 100 };

  public pay(paymentAmount: number) {
    this.wallet.cash -= paymentAmount;
  }
}

class PayBillService {
  public handle(paymentAmount: number): void {
    const customer = new Customer();
    customer.pay(paymentAmount);
  }
}

new PayBillService().handle(10);

Статьи по Теме

Искусство энбаггинга Энди Ханта и Дэйва Томаса

https://media.pragprog.com/articles/jan_03_enbug.pdf

TellDontAsk, Мартин Фаулер

https://martinfowler.com/bliki/TellDontAsk.html