Сегодня я научился — 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, и если вы хотите увидеть код лучше, вы можете взглянуть на этот репозиторий