DDD: Как отделить модели и логику от базы данных?

Обсуждаем, как правильно строить приложения
Ответить
yujin1st
Сообщения: 180
Зарегистрирован: 2012.03.26, 12:03

DDD: Как отделить модели и логику от базы данных?

Сообщение yujin1st » 2019.05.14, 11:43

Здравствуйте. Есть общий вопрос: как отделить модели и логику от базы данных?
Например, обычный магазин с обработкой заказов. Item, Order, OrderItem
Подскажите, пожалуйста, как ответить на него для двух конкретных ситуаций:

1. Как сделать процесс смены статуса заказа?
Нужно чтобы любой компонент системы (например внешняя CRM) мог обратится к заказу, поменять статус и цепочка запустилась: сохранилось в базу, отправились уведомления и т.д
В AR набросать просто:

Код: Выделить всё

class Order{
  public function changeStatus($newStatus){
    $this->status = $newStatus;
    $this->save(false); // или updateAttributes()
    $this->trigger('statusChanged');
  }
}
А как сделать это в терминологии DDD?
Доменная модель же не должна знать о базе. Кто будет отвечать за сохранение, когда мы вызовем $order->changeStatus('updated') ?

2. Как запрашивать разные связные данные для одних тех же моделей?
Ситуация: Отображение заказа у клиента и у менеджера.
С одной стороны, клиент в своем заказа человек видит товары (с картинками) и сумму. Мы через репозитарий получаем модель заказа и входящие товары.
А с другой менеджер будет видеть закупочную стоимость (представим, что есть цепочка работы со складом: Contractor, ItemContractor (item, price)), будет видеть цену доставки, будет видеть, но ему не нужно описание товара)

То есть модель вроде одна и есть Order, но набор данных для нее разный.
Здесь же другой вопрос: с AR мы можем легко через relation'ы в карточке заказа вывести и информацию о поставщике и его бабушке, а в случае c отдельными репозитариями, получается выборка данных превращается в головоломку.
И самое главное получается что в одной и той же модели в разных контекстах в модели может не быть разных данных?

noLogicOnlyWar
Сообщения: 77
Зарегистрирован: 2017.07.04, 20:53

Re: DDD: Как отделить модели и логику от базы данных?

Сообщение noLogicOnlyWar » 2019.05.16, 13:55

1) В книге ddd in php описывается ровно ваш пример
2) современные датамаперы прекрасно работают с realtion'ами, никакой проблемы нет. Если вы думаете что вам нужен репоризиторий и на Order и на OrderInfoBlablabla то это не так, репозиторий создается для агрегатов в отношение 1 к 1му. В вашем случае у вас только 1 реп для Order.

yujin1st
Сообщения: 180
Зарегистрирован: 2012.03.26, 12:03

Re: DDD: Как отделить модели и логику от базы данных?

Сообщение yujin1st » 2019.05.16, 14:27

Спасибо, что отвечаете =)

1. Да, прочитал книгу и смотрел пример с желаниями. И я не понял как это повторить.
Там повсюду используются сервисы приложения, и в частности в silex'e они и вызываются.
На вопрос, как в доменной модели вызвать событие, которое потом сохранится в базе я не нашел там ответа.
Еще пример, удаление желания - DeleteWishService, обращается к модели User, которая убирает желание из внутреннего массива. Как это попадает в базу?

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

2. То есть получается мы делаем агрегаторы ClientOrderCreate, ClientOrderView, AdminOrderViewFull, AdminOrderViewShort на каждый чих и не будет одной модели Order ибо она будет слишком много знать?

noLogicOnlyWar
Сообщения: 77
Зарегистрирован: 2017.07.04, 20:53

Re: DDD: Как отделить модели и логику от базы данных?

Сообщение noLogicOnlyWar » 2019.05.16, 15:12

На вопрос, как в доменной модели вызвать событие, которое потом сохранится в базе я не нашел там ответа
Не очень понятно о чем речь. Если надо сохранить где либо событие то используйте специальный подписчик.
Еще пример, удаление желания - DeleteWishService, обращается к модели User, которая убирает желание из внутреннего массива. Как это попадает в базу?
За это отвечает датамапер, в этой конкретной книге используется doctrine.
2. То есть получается мы делаем агрегаторы ClientOrderCreate, ClientOrderView, AdminOrderViewFull, AdminOrderViewShort на каждый чих и не будет одной модели Order ибо она будет слишком много знать?
Нет у вас один агрегат - order. Думаю вы не совсем понимаете что это. Что такое агрегат есть кратко в ddd in php и более подробно у Вернона.
Я понимаю, что доменный слой не должен знать о базе в принципе, но тогда как реализовать изменение данных и их сохранение?
другая же модель не будет обращаться к сервисам?
Да не должен. Представьте если бы ваши сущности хранились не в бд а например в массиве. У вас есть набор сущностей order. И есть коллекция где вы их храните - массив php. Как вы изменяете сущность order в коллекции? Вы достаете конкретный order изменяете его состояние и все, апдейт есть. Как вы сохраняете новый order в коллекции? делаете $orderCollection[] = $order.
В этом суть абстракции которую дает вам репозиторий. Для доменного слоя прозрачно куда в конечном счете сохранятся ваши сущности - в базу данных, в массив или куда то еще, домен работает с репозиторием который предоставляет интерфейс коллекции как будто наши сущности лежат в памяти.

Ответить