我在域层中有一个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);
//[...]
}
这需要向我的控制器添加更多业务逻辑,我想避免。
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
}
这降低了我的UI层的复杂性,并且没有在应用程序层之上公开业务逻辑。
也许这些示例比DDD更像CRUD,但我想以更简单的方式公开我的用例之一。
在这种情况下,应使用哪种解决方案?有没有更好的方法来处理DDD中的“获取或创建”逻辑?
我不确定这是否是您想听到的答案,但基本上我认为您正在处理偶然的复杂性,并且您正在尝试解决错误的问题。
在继续之前,我会强烈建议您考虑以下问题:
上述问题的答案应指导您做出决定。
重要:另外,请注意,您上面的两个方法都有一个小窗口,其中两个并发请求都可以成功存储报告。
根据个人经验,我建议:
UserMonthlyReport
或其他,您可以在运行时强制执行。当然,这更复杂,并且可能需要做更多的工作,但是,如果有一个不变量的商业案例,那么这就是您应该做的。 (再次,我怀疑报告是否需要它,但是我在这里以护理报告为例,或为将来的读者编写了它。)>