Domain driven design DDD-具有基础架构实现的域服务

Domain driven design DDD-具有基础架构实现的域服务,domain-driven-design,ddd,Domain Driven Design,Ddd,我正在使用六边形架构在DDD中实现一个项目。 我试图遵循所有避免贫血领域模型的最佳实践,但我遇到了这个问题。 我有一个具有属性优先级的实体客户机,为了计算这个优先级,我使用一个对外部API的rest调用 我想避免在实体上使用setPriority方法,所以我提出了这个解决方案,但我不确定它是否真的“符合DDD”。 此处为伪代码: //DOMAIN interface PriorityService { public int exec(Client client); } class Clie

我正在使用六边形架构在DDD中实现一个项目。 我试图遵循所有避免贫血领域模型的最佳实践,但我遇到了这个问题。
我有一个具有属性优先级的实体客户机,为了计算这个优先级,我使用一个对外部API的rest调用
我想避免在实体上使用setPriority方法,所以我提出了这个解决方案,但我不确定它是否真的“符合DDD”。
此处为伪代码:

//DOMAIN
interface PriorityService {
  public int exec(Client client);
}

class Client {
....
  public void calculatePriority(PriorityService service) {
    this.priority = service.exec(this);
  }
}

//INFRASTRUCTURE
class ThirdPartyPriorityService implements PriorityService{
  ...
  public int exec(Client client) {
    int priority = this.externalApi(...);
    return priority; 
  }
}
我发现这种方法对于集成第三方服务非常简单有效,实体是其内部状态一致性的唯一负责人,但我可以轻松集成不同的系统。
是否有更好的方法(最好不使用setter)?

有没有更好的方法(最好不用setter)

也许吧。考虑:

设计是我们为了得到更多我们想要的东西而做的事情,而不是仅仅通过设计就能得到的东西——露丝·马兰

是否有“更好的方法”将取决于您上下文中的“我们想要什么”

当Eric Evans在2003年描述时,他希望将域代码从“管道”中分离出来——我们应该能够描述业务,而不会让我们的代码受到数据库字符串和事务等的污染

public void calculatePriority(PriorityService service) {
  this.priority = service.exec(this);
}
里德尔:在这个设计中,你是如何处理这个事实的?如果您的解决方案将具有弹性,那么您将需要某种逻辑,以确保系统在网络不可用、远程服务器脱机进行维护、凭据过期等情况下正常运行

用不同的方式表达同样的想法:从web服务器获取HTTP响应就是I/O,I/O“污染”了所有与之接触的东西。因此,
ThirdPartyPriorityService
是I/O,因此,
Client::calculatePriority
是I/O

同样的想法:我们的HTTP客户机必然存在于“命令shell”(commissive shell)中,通过将客户机注入到域代码中,我们实际上使域代码成为命令shell的一部分

另一种方法是认识到
ThirdPartyPriorityService
正在从某个远程位置检索信息,而这种关注可能真正属于应用程序,而不是域--域代码关心的是信息是什么,而不是信息来自何处

例如,您可以更改您的实现,以便应用程序调用优先级服务,然后将优先级传递给域模型。请参阅关于协议库的

以这种方式设计代码并不比另一种方式好或坏;这是一套不同的折衷方案

如果我们未能使我们的计划与我们当时理解的正确思考我们财务目标的方式保持一致,那么我们将不断地因分歧而绊倒,这将使我们的速度减慢--

如果代码实际上是按照您认为的方式工作的,那么您对更改代码的估计可能会更好。这可能是一个有价值的“我们想要的”

有没有更好的方法(最好不用setter)

也许吧。考虑:

设计是我们为了得到更多我们想要的东西而做的事情,而不是仅仅通过设计就能得到的东西——露丝·马兰

是否有“更好的方法”将取决于您上下文中的“我们想要什么”

当Eric Evans在2003年描述时,他希望将域代码从“管道”中分离出来——我们应该能够描述业务,而不会让我们的代码受到数据库字符串和事务等的污染

public void calculatePriority(PriorityService service) {
  this.priority = service.exec(this);
}
里德尔:在这个设计中,你是如何处理这个事实的?如果您的解决方案将具有弹性,那么您将需要某种逻辑,以确保系统在网络不可用、远程服务器脱机进行维护、凭据过期等情况下正常运行

用不同的方式表达同样的想法:从web服务器获取HTTP响应就是I/O,I/O“污染”了所有与之接触的东西。因此,
ThirdPartyPriorityService
是I/O,因此,
Client::calculatePriority
是I/O

同样的想法:我们的HTTP客户机必然存在于“命令shell”(commissive shell)中,通过将客户机注入到域代码中,我们实际上使域代码成为命令shell的一部分

另一种方法是认识到
ThirdPartyPriorityService
正在从某个远程位置检索信息,而这种关注可能真正属于应用程序,而不是域--域代码关心的是信息是什么,而不是信息来自何处

例如,您可以更改您的实现,以便应用程序调用优先级服务,然后将优先级传递给域模型。请参阅关于协议库的

以这种方式设计代码并不比另一种方式好或坏;这是一套不同的折衷方案

如果我们未能使我们的计划与我们当时理解的正确思考我们财务目标的方式保持一致,那么我们将不断地因分歧而绊倒,这将使我们的速度减慢--


如果代码实际上是按照您认为的方式工作的,那么您对更改代码的估计可能会更好。这可能是一个有价值的“我们想要的”。

谢谢你的回答。我省略了代码库的很大一部分,实际上在infrastructureException和DomainException之间有一些映射。我也有一个回退策略,但我忽略了它,因为我的主要任务是保持域模型的一致性,并找出这种方法是否违反了“DDD纯度,如果我的架构”,谢谢你的回答。我漏掉了一大把