Я просмотрел SO и другие форумы/списки рассылки в поисках ответов на эту тему, и хотя я знаю, что ответ во многом зависит от самого домена и того, что приемлемо с точки зрения возможной согласованности, я все еще изо всех сил пытаюсь найти хорошее решение.
Проблема связана с тем, где проверять бизнес-правила, соответствующие домену.
Мой домен — это торговая площадка в Интернете. Участник (с ролью Продавец) может разместить объявление о продаже товара. Продавец может указать минимальное и максимальное количество товаров, которые можно приобрести в одном заказе, а также цену товара.
Покупатель может купить товар по определенному объявлению. Необходимо соблюдать следующие правила:
- Они могут указать количество предметов, которые они хотели бы купить, которое должно быть между минимальным и максимальным значением, разрешенным в объявлении.
- Они должны быть активными (поскольку участники могут быть забанены).
- Объявление должно быть активным (реклама может быть приостановлена).
My Market BC занимается рекламой и покупками. Я разработал его следующим образом:
- Совокупный корень объявлений
- Член АР
- КупитьТранзакция AR
Я борюсь с тем, как и где проверить приведенные выше бизнес-правила, которые в данном случае охватывают несколько агрегатов. В идеале у меня был бы метод:
$buyer->buy($adId, $quantity);
Это будет вызвано командой BuyItems
$buyCommand = new BuyItems($adId, $qty);
В совокупности участников.
Из вариантов я понимаю, что у меня есть:
Проверять вне домена, на внешнем уровне — это означает, что я буду проверять команду перед отправкой в домен. Это подразумевало бы некоторую утечку логики за пределы домена, но я бы извлек рекламу из модели чтения, проверил ограничение (между минимумом и максимумом, активным объявлением, активным пользователем), а затем отправил команду. В этом случае я бы также выполнил проверку на стороне домена в виде диспетчера процессов, который выдал бы компенсирующее действие или, по крайней мере, предупредил бы, если возникнет несоответствие.
Определите интерфейс службы в домене и реализуйте службу, которая получает данные из модели чтения, а затем проверяете их в обработчике команд, вызывая службу. Если данные недействительны, сгенерируйте исключение. Здесь также должна была бы произойти проверка домена, потому что модель чтения может быть несогласованной (опять же с использованием диспетчера процессов).
Загрузите сводные корни Ad и Member в обработчик BuyItem и передайте их $buyer->buy($ad, $member, $qty); затем в методе buy() в AR проверьте, что количество находится между min и max. На самом деле не чувствую себя комфортно с этой опцией, так как я понимаю, что пытаюсь втиснуть согласованность транзакций, когда она мне действительно не нужна (в то время как мне нужно минимизировать риски команд с неограниченным количеством или неактивным членом , это не имеет большого значения, если это произойдет, и я после этого приму меры по исправлению положения, поэтому меня вполне устраивает возможная согласованность).
Может ли кто-нибудь указать мне, какой лучший вариант для этого сценария?