DDD как орагнизовать валидацию. Как возвращать значения из handler?

Обсуждаем, как правильно строить приложения
Ответить
i-programmer
Сообщения: 101
Зарегистрирован: 2015.08.24, 18:50

DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение i-programmer »

В этом топике viewtopic.php?p=188542#p188542 показано было что команда, по сути - это dto, а handler - сервис.

Я вижу что команда имеет метод execute а хэндлеры - handle. Все они работают по паттерну "Команда", как я понимаю, а значит ничего не должны возвращать. Максимум true/false разве что. А что где и как надо делать, чтобы вернуть что-то клиенту? Например надо данные по отчёту. В целом handler будет GetEquipmentReportHandler. И что он должен сделать?)) Или что-то рассчитать и отдать результат. Не понимаю как это работает в рамках команд и хэндлеров


-----


И по поводу валидации. Тут viewtopic.php?p=188218#p188218 Дмитрий показывал валидацию с применением моделей фреймворка. Предположим я не хочу её использовать. Будет какая-то своя валидация. Часть общей валидации я могу написать сам (проверка что значение число или что email - по правилам написан и т.д.), всё будет складироваться в массив $errors и возвращаться на клиент, если не пустой. Но что делать, если в форме присутсвует как базовая валидация, так и валидация бизнеса, например, что номер объекта должен быть не больше 9999 или что если "учитывать X", то нужно обязательно заполнить поле "Y" и "Z"? В домене правило - если что-то не так - выбросить исключение. На каждое бизнес правило дёргать пользователя - как-то не хорошо. А пачкой сделать - не знаю как. С AR было просто))
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение ElisDN »

i-programmer писал(а): 2022.04.05, 19:13 А что где и как надо делать, чтобы вернуть что-то клиенту? Например надо данные по отчёту.
Команды нужны только для операций на изменение. А для отображения данных нужны отдельные запросы.
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение ElisDN »

i-programmer писал(а): 2022.04.05, 19:13 На каждое бизнес правило дёргать пользователя - как-то не хорошо. А пачкой сделать - не знаю как. С AR было просто))
Вместо одной большой универсальной CRUD-формы удобнее делать отдельные бизнес-операции с маленькими формами. Тогда многое упростится и дёрнуть пользователя всего два раза будет не так плохо.
i-programmer
Сообщения: 101
Зарегистрирован: 2015.08.24, 18:50

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение i-programmer »

ElisDN писал(а): 2022.04.06, 12:31
i-programmer писал(а): 2022.04.05, 19:13 А что где и как надо делать, чтобы вернуть что-то клиенту? Например надо данные по отчёту.
Команды нужны только для операций на изменение. А для отображения данных нужны отдельные запросы.
Но ведь в запросах на изменение нам тоже иногда нужно отдать какой-то результат. Например у меня есть операция формирования узла дерева с данными. Но индивидуальный номер узла может сгенерироваться только на сервере (из-за особенностей дерева). Когда приходит запрос на формирование узлов, я делаю операцию сохранения и возврат данных, где хранятся все узлы, которые смогли сохраниться в БД с их идентификаторами и опциями, чтобы клиент уже вставил их при успешности операции. Как-то так.

В любом случае вопрос был как данные клиенту отдать, даже если отдельным запросом........Но на сколько я успел посмотреть информацию, у метода handle тип возвращаемого значения mixed и можно возвращать что угодно, в зависимости от нашей необходимой логики. Я думал просто, что и command и handler всегда возвращабт ислключительно void. Если я не прав, пожалуйста поправьте.
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение ElisDN »

i-programmer писал(а): 2022.04.06, 21:30 Я думал просто, что и command и handler всегда возвращают исключительно void. Если я не прав, пожалуйста поправьте.
Если мы запускаем команду сразу, то да, можно вернуть идентификаторы из обработчика. В простейшем случае такое сработает.

Но в более сложных модульных или микросервисных проектах команды вместо выполнения в контроллере могут отправляться в очередь и запускаться уже там в фоновых воркерах. Так из команды мы ничего в контроллер вернуть не сможем. В этом случае все идентификаторы генерируют сразу в контроллере (или на клиенте) и их переедают в команду и сразу возвращают клиенту.
i-programmer
Сообщения: 101
Зарегистрирован: 2015.08.24, 18:50

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение i-programmer »

ElisDN писал(а): 2022.04.06, 23:33
i-programmer писал(а): 2022.04.06, 21:30 Я думал просто, что и command и handler всегда возвращают исключительно void. Если я не прав, пожалуйста поправьте.
Если мы запускаем команду сразу, то да, можно вернуть идентификаторы из обработчика. В простейшем случае такое сработает.

Но в более сложных модульных или микросервисных проектах команды вместо выполнения в контроллере могут отправляться в очередь и запускаться уже там в фоновых воркерах. Так из команды мы ничего в контроллер вернуть не сможем. В этом случае все идентификаторы генерируют сразу в контроллере (или на клиенте) и их переедают в команду и сразу возвращают клиенту.
Возьмём rest от vk.

Добавление друга: https://dev.vk.com/method/friends.add
Результат
После успешного выполнения возвращает одно из следующих значений:
1 — заявка на добавление данного пользователя в друзья отправлена;
2 — заявка на добавление в друзья от данного пользователя одобрена;
4 — повторная отправка заявки.
или удаление https://dev.vk.com/method/friends.delete
Результат
После успешного выполнения начиная с версии 5.28 возвращается объект с полями:
success — удалось успешно удалить друга;
friend_deleted — был удален друг;
out_request_deleted — отменена исходящая заявка;
in_request_deleted — отклонена входящая заявка;
suggestion_deleted — отклонена рекомендация друга.
То есть нельзя сразу что-то отдать на клиент, т.к. не известен результат операции.

Это простейшая операция получается и это ок? (Видимо с микросервисами я не работал и не совсем понимаю отличия "простой" от "сложной". Для меня всегда "есть запрос" и "есть ответ" )
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение ElisDN »

i-programmer писал(а): 2022.04.07, 08:06 Добавление друга friends.add (возвращает 1, 2, 4)
Удаление friends.delete (возвращает friend_deleted, out_request_deleted, in_request_deleted, suggestion_deleted)

То есть нельзя сразу что-то отдать на клиент, т.к. не известен результат операции.
Здесь результат неизвестен потому, что это обобщающие запросы, которые внутри выполняют какую-то одну из кучи операций. И мы не знаем заранее, что там выполнится. Поэтому понять что случилось мы можем только по возвращённому результату.

Но если бы там были отдельные запросы для каждой операции:
Отправка своей заявки friend.request (void)
Отзыв своей заявки friend.cancel (void)
Принятие чужой заявки friend.approve (void)
Отклонение чужой заявки friend.reject (void)
Отклонение рекомендации suggestion.reject (void)
...
то каждая могла бы ничего не возвращать в случае успеха. Или вернуть только ошибку.
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DDD как орагнизовать валидацию. Как возвращать значения из handler?

Сообщение ElisDN »

i-programmer писал(а): 2022.04.07, 08:06 Видимо с микросервисами я не работал и не совсем понимаю отличия "простой" от "сложной". Для меня всегда "есть запрос" и "есть ответ"
Дело не в простоте/сложности, а в синхронности/асинхронности.

При классической синхронной работе мы операцию запускаем сразу из контроллера и можем сразу вернуть готовый ответ вроде "Узел 36 добавлен" с результатом.

При асинхронной работе мы команду не запускаем сразу в контроллере, а записываем в очередь. Результата у нас ещё нет, поэтому можем показать клиенту сообщение вроде "Заявка в обработке" и по WebSocket ждать уведомление с результатом.

То есть при синхронной работе у нас "есть запрос" и сразу на него "есть ответ".
А при асинхронной работе через очередь у нас "есть запрос", но на него ещё "нет ответа".
Ответить