Client {
function changeManager(Manager $manager) {
if ($manager->isSomething()) {
$this->doSomething();
}
if ($manager->isSomethingElse() && $this->isSomething) {
$this->doSomethingElse();
$manager->doSomething();
}
$this->managerId = $manager->getId();
$this->events[] = new ManagerChangedEvent($clientId, $managerId);
}
}
CommandHandler {
function execute(ChangeManager $command) {
// ...
$eventDispatcher->dispatch($client->flushEvents())
}
}
CommandHandler {
function execute(ChangeManager $command) {
// ...
// как-то это "грязно"
if ($client->inStatus() && $client->managerId() != $newManager->getId()) {
$client->changeManager(Manager $manager);
$rpc->action();
$notifier->send();
// и т.д.
}
}
}
Ты не должен менять состояние Manager'а внутри Client'а.PHP:$manager->doSomething();
Не понял. Слушателе события, а откуда я его там считаю? Можешь немного подробнее обрисовать идею или ссылку на примерчик?Ты можешь просто прочитать состояние в слушателе.
Да, это сюда же, к этому вопросу и его расширение. При выполнении действий могут требоваться и действия предметной области над связанными сущностями, например при изменении статуса клиента нужно так же что-то проделать и с его менеджером. Или ещё такой кейс - при увольнении менеджера освободить всех его клиентов...Ты не должен менять состояние Manager'а внутри Client'а.
По id из события достать из базы клиента и узнать его статус. Ещё один вариант: подписаться на событие StatusChangedEvent, таким образом ты будешь сообщать о статусе.Не понял. Слушателе события, а откуда я его там считаю?
Клиент сгенерирует событие, по событию можно выполнить команду ЧтоТоПроделайСМенеджером($managerId, ...).При выполнении действий могут требоваться и действия предметной области над связанными сущностями, например при изменении статуса клиента нужно так же что-то проделать и с его менеджером.
Ну, вот за пример возьмем изменение менеджера закрепленного за клиентом.Проще общаться, если речь идет о каких-то конкретных понятиях, а не о doSomething и doSomethingElse.
В данном случае статус клиента не изменится (статусами может быть, например "должник", "новый клиент", "просрочен договор", "в проработке" и т.п.), только поменялся его менеджер.Ещё один вариант: подписаться на событие StatusChangedEvent, таким образом ты будешь сообщать о статусе.
Это да, но если к примеру для действий (логирования например) мне нужны состояния до действия и после? Я всё-таки думаю два DTO со всеми основными данными сущности в событие отдавать, до и после действия. А уж если для него какие-то специфичные нужны, их уже считывать в самом отдельно.По id из события достать из базы клиента и узнать его статус.
В данном — нет. Но в принципе статус когда-то меняется? Вот тогда и происходит событие.В данном случае статус клиента не изменится (статусами может быть, например "должник", "новый клиент", "просрочен договор", "в проработке" и т.п.), только поменялся его менеджер.
Для упрощения жизни ты можешь предыдущий статус добавлять в событие. Но строго говоря, если ты подписываешься на событие StatusChangedEvent, то ты можешь узнать предыдущий статус, если ты его куда-то записываешь.Это да, но если к примеру для действий (логирования например) мне нужны состояния до действия и после? Я всё-таки думаю два DTO со всеми основными данными сущности в событие отдавать, до и после действия. А уж если для него какие-то специфичные нужны, их уже считывать в самом отдельно.
UP, т.к. затерялось в обсуждении других вопросов. На вскидку примеры которые приходят в голову:Или ещё такой кейс - при увольнении менеджера освободить всех его клиентов...
Туда же вынести, где и вспомогательные действия не относящиеся к домену выполнять?
И как это чисто технически организовать лучше, ведь в отдельных случаях зависимых сущностей, над которыми нужно произвести действие может быть очень много. И в итоге возможно всё сводится к UPDATE ... WHERE rel=1, но теория предполагает загрузить в память несколько десятков/сотен объектов и отдельно произвести действия и сохранить.
$clients = $clientRepository->findByIds(); // выгружать полсотни или больше сущностей для простого multiple insert?
$ct = CallTask::create($clients); // или $ct->addClient(Client $client);
$repository->save($ct);
DDD way требует именно нескольких апдейтов, даже если их будет несколько сотен. Просто обычно это делается асинхронно.Пример 1. При увольнении менеджера необходимо отвязать от него всех клиентов (точнее его от клиентов, $client->changeGeneralManager() или $client->removeGeneralManager() которых может быть от нескольких штук, до многих десятков). Соответственно пару-тройку сотен объектов закгружать в память, делать это в цикле и потом для каждого делать апдейт ($repository->save()) не выглядит здорово, когда чисто технически всё сводится к UPDATE ... WHERE rel_field=1.
Из твоего примера не очень ясно зачем загружать клиентов, просто id-шники не подходят?Пример 2. Добавление клиентов в задания на прозвон колл-центру (холодные звонки или ещё что-то в таком роде). В UI, допустим, менеджер выбирает полсотни клиентов и сабмитит. На уровне инфраструктуры всё сводится к multiple insert. Но в домене должно быть что-то вроде:
PHP:$clients = $clientRepository->findByIds(); // выгружать полсотни или больше сущностей для простого multiple insert? $ct = CallTask::create($clients); // или $ct->addClient(Client $client); $repository->save($ct);
Подходят, пока бизнес-правила не требуют, что-то такое:Из твоего примера не очень ясно зачем загружать клиентов, просто id-шники не подходят?
function addClient(Client $client) {
if ($client->isActive() && $client->sonethingElse()) {
}
throw exception ClientCantBeAdded;
}