Услуги ДДД


Сегодня я научился — 04/05/2022

  • Агрегаты
  • Ценностные объекты
  • Услуги
  • Реализация

Агрегаты

Агрегат — это стандарт в DDD, когда набор объектов домена и объектов значений может рассматриваться как единое целое.

Ценностные объекты

Объекты значений — это, как говорит само название, объект, который не имеет связанных операций, он служит только для хранения значений. В приведенном выше примере, Адрес — это объект значений, потому что когда человек переезжает на другую улицу, даже если единственная часть, которая изменилась — это улица, мы не говорим, что он ОБНОВИЛ улицу в адресе, но что он ИЗМЕНИЛ адрес, что в системе переводится в новый объект значений, а не в обновление внутри существующего объекта значений.

Услуги

Когда мы говорим о DDD, услуга — это операция без статических данных, которая выполняет конкретную задачу домена. Лучшим признаком того, что нам следует создать сервис, является ситуация, когда мы хотим выполнить операцию, которая не имеет смысла в качестве метода в объекте Aggregate или Value.

Берегите себя
  • Если в проекте много услуг, это может указывать на то, что агрегаты анемичны
  • Сервисы являются Stateless, что означает, что они не переносят значения от одного вызова к другому

Реализация

Для той же самой системы, показанной выше, мы можем иметь, например, объект заказа, который содержит товары в качестве объекта значения

export class Order{ 
  private _id: string;
  private _customerId: string;
  private _items: OrderItem[];
  private _total: number;

  constructor(id: string, customerId: string, items: OrderItem[]){
    this._id = id;
    this._customerId = customerId;
    this._items = items;
    this._total = this.total();
  }

  total(): number{
    return this._items.reduce((acc, item) => acc + item.price, 0)
  }

}
Войдите в полноэкранный режим Выход из полноэкранного режима

В этом классе заказов у нас есть метод для возврата общей суммы конкретного заказа, но что если мы хотим вычислить общую сумму всех заказов? Не имеет смысла оставаться в качестве метода заказа, потому что этот метод должен будет получать другие заказы, чтобы произвести расчет, в этом случае мы должны создать службу Orders

export class OrderService{
  static total(orders: Order[]): number {
    return orders.reduce((acc, order) => acc + order.total(), 0);
  }
}
Войдите в полноэкранный режим Выход из полноэкранного режима

OrderService может содержать все методы, которые не имеет смысла размещать внутри Order, включая, например, создание нового заказа

export class OrderService{
  static total(orders: Order[]): number {
    return orders.reduce((acc, order) => acc + order.total(), 0);
  }

  static placeOrder(customer: Customer, items: OrderItem[]): Order{
    if(items.length === 0){
      throw new Error("Order must have at least one item")
    }

    const order = new Order(uuid(), customer.id, items);
    return order
  }
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Я все еще изучаю DDD, и если вы хотите увидеть код лучше, вы можете взглянуть на этот репозиторий

Оцените статью
Procodings.ru
Добавить комментарий