DDD, сервисные слои и вопросы

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

DDD, сервисные слои и вопросы

Сообщение yujin1st » 2018.12.18, 16:12

Пытаюсь встроить текущие процессы в рамки DDD и возникают вопросы. Помогите разобраться, пожалуйста.

Есть обычный магазин с обычными сущностями: Item (id, title, quantity), Order(id, status, userId) , OrderItem (id, orderId, quantity, price), и с двусторонней синхронизацией со внешней CRM (обмениваемся каталогами, складами и заказами).

1. Как правильно встроить многоступенчатые (лог -> email -> смс) уведомления о смене статуса заказа? Вопрос скорее относиться к тому как правильно работать с декораторами?

Например у модели Order есть метод changeStatus($newStatus) и внутри вызывается событие OrderUpdateStatusEvent, вызываемый внутри оного. Так же объявляем интерфейс сервиса NotificationServiceInterface,

1.1 Как будет правильно вызвать этот метод?
- внутри changeStatus (надо еще придумать как, чтобы было без протечки) обратиться к сервису
- где-нибудь отдельно подвязываться к событию и сделать обработчик на событие и в нем обратиться к сервису

1.2. Как будет правильно реализовать сами уведомлени?
- в одной реализации сервиса описать все методы? (вариант на самом деле не очень, поэтому перехожу ко второму)
- сделать через декораторы: один класс email, другой sms, итд. Вопрос в том как сделать вызов всех существующих декораторов и еще не написанных (например потом захотели бы во внешнеюю систему отправить)

2. Синхронизация с внешней подсистемой. Как изменять данные снизу-вверх, и как недопустить зацикливания?

Здесь относительно вроде понятно. Сам код относится к инфраструктуре, подписывается на события связанные с заказами и отправляет данные куда надо.
Например, мы можем поменять заказ через Order->updateOrder($updateOrderDto) (со всей сопутствующей цепочкой). Теперь мы меняем заказ во внешней системе, и шлем данные обратно к нам.

2.1 Как избежать цикла?
Мы пытаемся обновить заказ через updateOrder -> он отправляет событие -> мы отправляем данные опять в crm. Где поставить флаг, что надо пропустить обработку?

2.2. Как пересчитать остатки на складе?
В нашей системе есть модуль склада, к которому обращается модуль магазина с проверками наличия товара, а также с вызовами на предмет пересчета. Сам склад событий не имеет.
Получается чтобы не потерять данные мы всегда должны обращаться только сверху-вниз, т.е через заказы, но никогда нельзя напрямую к тем же складам, верно?

То есть, например, в crm обновилось количество товара в одном из заказов - мы все равно должны поменять их через заказ, если не предусмотрено иное, верно?


3. Хранение доп.данных и репозитарии.


3.1 как быть с CrmExternalId
Для синхронизации с внешней подсистемой мы запоминаем externalId для заказов и товаров.
Как и куда положить этот externalId?.
Обычно без ddd, привычнымы нажатиями клавиш вносим externalId в таблицы с сущностями, добавить поля к моделям и продолжить работать как ни в чем не бывало.

Как быть здесь? вроде проблема решается отдельными таблицами: ItemExtrenalCrm (itemId,externalCrm) итд, но когда надо например обновить полный каталог товаров из нескольких десятков тысяч позиций как мы должны обращаться к ним? Репозитарий Item не знает о внешних данных. Ладно можно джойнить когда относительно немного строк в таблицах. Но как это дело оптимизировать когда нужна будет скорость?


3.2 Когда сохранять данные?

Есть сервис редактирования заказа (OrderUpdateService), который обращается к одному из заказов через updateOrder. И внутри метода мы, например, пересчитываем скидки по товарам в заказе. Где должно быть сохранение? В сервисе или в методе модели? По идее в сервисе, который знает о репозитории и может вызвать метод сохранения там.

Тогда как как должен обращаться к заказу и сохранять заказ модуль синхронизации с crm?
- Вызывать сервис и через dto отправлять данные?
- Обращаться самостоятельно к репозитарию, менять данные и вызывать сохранение?

Вопрос в том как в какой-то момент, например, поменять статус заказа через его метод и не забыть сохранить его?

В книге Domain-Driven Design in PHP by Carlos Buenosvinos, Christian Soronellas, and Keyvan Akbary (https://leanpub.com/ddd-in-php) люди используют доктрину, но у меня еще нет понимания как это работает.
Есть ли способы проще?


4. Шина команд и обработка исключений

тут шина команд обсуждалась с хорошими примерами в viewtopic.php?f=34&t=36725&start=60#p188542

Вопрос в том как ловить исключения? Контроллер должен объявлять try catch со списком всех возможных исключений и портянкой на это дело? или есть способ попроще?

anton_z
Сообщения: 416
Зарегистрирован: 2017.01.15, 15:01

Re: DDD, сервисные слои и вопросы

Сообщение anton_z » 2018.12.23, 13:24

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

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

Re: DDD, сервисные слои и вопросы

Сообщение yujin1st » 2018.12.23, 19:31

Есть проблема, что при добавлении нового функционала кратно возрастает сложность кода и проверки, а также большая вероятность что отвалиться старое что-нибудь.
Поэтому, надеемся что ddd-подход решит именно проблемы роста проекта.

То есть текущий crud'овский подход хорошо работает на маленьких и несложных проектах, но что-то поувесистей уже выходит тяжко.
Описанный пример специально упрощенный. Сам проект куда сложнее и в нем много разных запутанных моментов из-за текущей архитектуры.

anton_z
Сообщения: 416
Зарегистрирован: 2017.01.15, 15:01

Re: DDD, сервисные слои и вопросы

Сообщение anton_z » 2018.12.24, 02:40

yujin1st писал(а):
2018.12.23, 19:31
Есть проблема, что при добавлении нового функционала кратно возрастает сложность кода и проверки, а также большая вероятность что отвалиться старое что-нибудь.
Поэтому, надеемся что ddd-подход решит именно проблемы роста проекта.
Я бы обвешал бы все тестами (пусть и с базой и с фикстурами), хотя бы приемочными/функциональными, рефакторил бы для получения тестабельного кода (когда уж совсем никак не тестится). DDD тут не панацея, я думаю, только свои сложности привнесет. Но это чисто мое мнение, Вы сами решайте.

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

Re: DDD, сервисные слои и вопросы

Сообщение yujin1st » 2018.12.24, 05:58

Не панацея, не спорю. Но в поисках. Есть ряд вещей завязанных на AR, которые сейчас вылазят боком, например: много логики в before\afterSave, логика завязанная на сценарии в модели. Эти решения не плохи, но когда модель толстеет за этим становится трудно уследить. Да, это решается рефакторингом, но него нужно время и так каждый раз когда появляется новый функционал. DDD вроде должен помощь именно с тем, что не надо будет каждый раз рефакторить старый код.
Я и не собираюсь переписывать весь проект, когда он работает сейчас, но что основное можно и уже начать работать с этим.

Аватара пользователя
maleks
Сообщения: 1722
Зарегистрирован: 2012.12.26, 12:56

Re: DDD, сервисные слои и вопросы

Сообщение maleks » 2018.12.24, 09:43

yujin1st писал(а):
2018.12.18, 16:12
В книге Domain-Driven Design in PHP by Carlos Buenosvinos, Christian Soronellas, and Keyvan Akbary (https://leanpub.com/ddd-in-php) люди используют доктрину, но у меня еще нет понимания как это работает.
Можете ознакомительно тут почитать. Или Фаулера про корпоративные шаблоны.
yujin1st писал(а):
2018.12.18, 16:12
Есть ли способы проще?
Посмотрите примеры как у Дмитрия в его инет магазине, там пример слоистой системы, что касается сущностей то без доктрины, на AR, которые используются только как доменные модели.
yujin1st писал(а):
2018.12.18, 16:12
Эти решения не плохи, но когда модель толстеет за этим становится трудно уследить. Да, это решается рефакторингом, но него нужно время и так каждый раз когда появляется новый функционал. DDD вроде должен помощь именно с тем, что не надо будет каждый раз рефакторить старый код.
Тут больше в помощь будет SOLID и, как сказали выше, тесты, чем абстрактный DDD.

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

Re: DDD, сервисные слои и вопросы

Сообщение yujin1st » 2018.12.24, 17:10

solid хороший принцип, а ddd - хороший способ организовать его, так что одно другому не мешает.
тем более лучше взять что-то уже рабочее, чем придумывать свой велосипед.

anton_z
Сообщения: 416
Зарегистрирован: 2017.01.15, 15:01

Re: DDD, сервисные слои и вопросы

Сообщение anton_z » 2018.12.25, 02:52

yujin1st писал(а):
2018.12.24, 17:10
тем более лучше взять что-то уже рабочее, чем придумывать свой велосипед.
Оно рабочее только в определенных условиях. Попадает ли ваш проект под эти условия? Вот это уже вопрос.

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

Re: DDD, сервисные слои и вопросы

Сообщение yujin1st » 2018.12.26, 05:16

Предложите более-менее общеизвестный и обсуждаемый вариант архитектуры для сложных приложений и я буду рад воспользоваться им.
Понятно что для каждого проекта свои особенности и прочее. Но факт фактом - по ddd есть книги, его обсуждают, про него хотя бы гуглятся примеры.
И это все оффтоп. Есть вопросы в начале темы, и на них как-то надо находить ответы.

anton_z
Сообщения: 416
Зарегистрирован: 2017.01.15, 15:01

Re: DDD, сервисные слои и вопросы

Сообщение anton_z » 2018.12.27, 09:58

yujin1st писал(а):
2018.12.18, 16:12

Есть обычный магазин с обычными сущностями
yujin1st писал(а):
2018.12.26, 05:16
Предложите более-менее общеизвестный и обсуждаемый вариант архитектуры для сложных приложений и я буду рад воспользоваться им.
Я думаю, что Вам поможет Объектно-ориентированный анализ и проектирование в купе с MVC. По ним тоже информации хоть отбавляй. Если ищете конкретную литературу могу порекомендовать книгу Крэга Лармана "Применение UML и шаблонов проектирования". Там в деталях расписано, как и что проектировать, с чего начинать. Абстракция от базы, построение гексагональной архитекуры (что подразумевает перечисленная Вами литература) тут избыточно, тем более что у Вас легаси проект. Он тестами то покрыт? Если нет, начните лучше с них, а не с DDD, вопросы отпадут сами.
Да, про DDD на просторах интернета и в книгах пишут многие и много, вопрос в том, ради чего они это делают и насколько можно им доверять, основана ли вся эта информация на реальном опыте применения или это просто человек изучил что-то и решил закрепить изученное написанием статьи.

Ответить