DDD关于设计决策

时间:2019-03-19 22:06:20

标签: domain-driven-design aggregateroot

我必须解决一个域问题,我对什么是更好的解决方案存有疑问。我将提出问题:

我有应用程序,每个应用程序有很多流程应用也有一些 ProcessSettings 。当我必须创建流程时,我有一些业务规则,例如,基于应用程序的流程设置,我必须在某些流程属性上应用一些规则。

我已将 Application 视为聚合根,将 Process 视为其他聚合根,并将ProcessSettings视为Application聚合内的值对象。

我有一个用例来创建流程,其逻辑是创建一个有效的流程实例并将其与ProcessRepository持久化。好吧,我想我有两个选择来应用流程设置:

  1. 在用例中,通过Application聚合中的域服务从Application聚合中按ApplicationId获取流程设置,然后将ProcessSettings传递给流程创建方法。
  2. 在用例中,要创建流程并通过“应用程序”聚合中的域服务传递流程的副本(值对象)以应用流程设置。

您认为哪种方法最适合使用?还是以其他方式实现?

谢谢!

1 个答案:

答案 0 :(得分:0)

  

我们的产品负责人告诉我们,如果客户在   片刻,并创建了一个流程,该设置将对此有效   如果客户端不更新它,则处理。如果客户离开支付   然后,当客户要更新该设置时,   系统不允许更新它,因为实际设置不会   适合过程数据

鉴于基于流程设置的验证仅在流程创建/更新方案中进行,因此这使实现更加容易。此外,我猜想竞争条件也与业务无关,例如,如果在创建/更新流程的同时更改设置。

鉴于此,我们可以假设ProcessSettingsProcess可以处于不同的一致性边界。换句话说,两者都可以是单独的聚合根的一部分。

此外,重要的是要认识到基于设置的验证不是Process不变式,这意味着Process不应该负责强制执行这些规则。由于这些不是不变式,因此您也不应争取始终有效的策略,而应使用延迟验证策略。

从那时起,有很多建模此用例的好方法,所有这些都可以归结为:

//Application layer service
void createProcess(processId, applicationId, data) {
    application = applicationRepository.applicationOfId(applicationId);
    process = application.createProcess(processId, data);
    processRepository.add(process);
}

//Application AR
Process createProcess(processId, data) {
    process = new Process(processId, this.id, data);
    this.processSettings.ensureRespectedBy(process);
    return process;
}

如果ProcessSettingsApplication AR的一部分,则可以在Application上放置工厂方法来创建进程,因为它拥有执行验证所必需的状态,例如在上面的示例中。这样就无需为该任务引入专用域服务,例如独立工厂。

如果ProcessSettings可以是它自己的聚合根,则可以始终这样做,但是引入用于设置的查找域服务:

//Application AR
Process createProcess(processId, data, settingsLookupService) {
    process = new Process(processId, this.id, data);
    processSettings = settingsLookupService.findByApplicationId(this.id);
    processSettings.ensureRespectedBy(process);
    return process;
}

有些人可能会说您的聚合不再是纯粹的,因为它正在通过调用settingsLookupService执行间接IO。如果要避免这种依赖性,则可以引入诸如ProcessDomainService之类的域服务来封装创建/更新逻辑,或者甚至可能认为查找逻辑不够复杂并将其直接放在应用程序层中。 / p>

//Application layer service
void createProcess(processId, applicationId, data) {
    processSettings = processRepository.findByApplicationId(applicationId);
    process = application.createProcess(processId, data, processSettings);
    processRepository.add(process);
}

我们没有办法告诉您哪种方法在您的特定情况下更好,有时甚至没有一种完美的方法,许多其他方法可能同样有效。根据经验,保持聚合纯净是个好主意,因为单元测试更容易(减少模拟)。