У меня есть DailyReport
сущность в моем доменном слое. В этом объекте есть несколько полей:
reportId
userId
date
tasks
- Коллекция вещи, которые пользователь делал в данный день; mood
- как пользователь себя чувствовал в течение всего дня;
Кроме того, в моей службе приложений есть несколько методов:
DailyReportService::addTaskToDailyReport
DailyReportService::setUserMoodInDailyReport
Дело в том, что оба эти метода требуют, чтобы DailyReport
было создано ранее или создано во время выполнения функции. Как справиться с этой ситуацией?
Я нашел 2 решения:
1 Создайте новый объект DailyReport
перед отправкой метода и после этого передайте им reportId:
//PHP, simplified
public function __invoke() {
$taskData = getTaskData();
/** @var $dailyReport DailyReport|null **/
$dailyReport = $dailyReportRepository->getOneByDateAndUser('1234-12-12', $user);
//there were no report created today, create new one
if($dailyReport === null) {
$dailyReport = new DailyReport('1234-12-12', $user);
$dailyReportRepository->store($dailyReport);
}
$result = $dailyReportService->addTaskToDailyReport($taskData, $dailyReport->reportId);
//[...]
}
Для этого требуется добавить больше бизнес логи c на мой контроллер, чего я хочу избежать.
2 : проверить в методе что DailyReport
существует, и создайте новый, если необходимо:
//my controller method
public function __invoke() {
$taskData = getTaskData();
$result = $dailyReportService->addTaskToDailyReport($taskData, '1234-12-12', $user);
//[...]
}
//in my service:
public function addTaskToDailyReport($taskData, $date, $user) {
//Ensure that daily report for given day and user exists:
/** @var $dailyReport DailyReport|null **/
$dailyReport = $dailyReportRepository->getOneByDateAndUser();
//there were no report created today, create new one
if($dailyReport === null) {
$dailyReport = new DailyReport($date, $user);
$dailyReportRepository->store($dailyReport);
}
//perform rest of domain logic here
}
Это уменьшает сложность моего уровня пользовательского интерфейса и не предоставляет бизнес-логики c выше уровня приложений.
Может быть, этот пример больше CRUD-i sh, чем DDD, но я хотел показать один из моих вариантов использования более простым способом.
Какое решение следует использовать, когда в этом случае? Есть ли лучший способ обработать логи get-or-create c в DDD?
EDIT 2020-03-05 16:21:
a 3 пример, это то, о чем я говорю в своем первом комментарии к Savvas Ответ:
//a method that listens to new requests
public function onKernelRequest() {
//assume that user is logged in
$dailyReportService->ensureThereIsAUserReportForGivenDay(
$userObject,
$currentDateObject
);
}
// in my dailyReportService:
public function ensureThereIsAUserReportForGivenDay($user, $date) {
$report = getReportFromDB();
if($report === null) {
$report = createNewReport();
storeNewReport();
}
return $report;
}
//in my controllers
public function __invoke() {
$taskData = getTaskData();
//addTaskToDailyReport() only adds the data to summary, does not creates a new one
$result = $dailyReportService->addTaskToDailyReport($taskData, '1234-12-12', $user);
//[...]
}
Это будет выполнено только тогда, когда пользователь войдет в первый раз / пользователь вошел в систему вчера но это его первая просьба в новый день. В моей бизнес-логике будет меньше сложности c, мне не нужно постоянно проверять службы / контроллеры, если есть отчет, созданный, потому что он был выполнен ранее в тот же день.