我正在开发一个实现DDD概念的Web应用程序,我知道DDD中的域服务是:
域服务:封装不自然的业务逻辑 适合域对象,并不是典型的CRUD操作 - 那些将属于一个存储库。
但我对域服务是域模型中的类,接口或方法以及我的聚合根/域实体如何调用该服务感到困惑?
是否需要将聚合根或域实体返回为域服务?
如果我的聚合根需要检查电子邮件是否存在,或者检查密码哈希匹配(需要调用服务/存储库来访问数据库)。我是否需要在域服务或应用程序服务中实现该代码?
答案 0 :(得分:3)
但我对域服务是域模型中的类,接口还是方法
感到困惑
Class
或Interface
,具体取决于抽象级别。在某些情况下,它需要一些第三方无状态(!)库,并且您将其作为基础结构层中的实现的接口(在此层中您可能调用第三方图书馆。)
我的聚合根/域实体将如何调用该服务
如果它是一个接口,那么您可以将服务传递给Aggregate的方法或在Aggregate外部调用它,并将输出作为Aggregate方法的参数传递(首选方法,因为它最小化Aggregate的依赖性)。
如果它是一个类,你也可以在Aggregate中实例化+使用它,但是这会创建从Aggregate到Domain服务的依赖关系;在每种情况下都没有错,但在使用之前你应该考虑一下。
是否需要将聚合根或域实体返回为域服务?
不,它可以返回驻留在Domain层中的任何内容(原始值或值对象)。
如果我的聚合根需要检查电子邮件是否存在,或者检查密码哈希匹配(需要调用服务/存储库来访问数据库)。我是否需要在域服务或应用程序服务中实现该代码? / p>
如果需要进行IO调用,那么它不是域服务,而是基础结构服务或应用程序服务。
如果我的聚合根需要检查电子邮件存在
在应用程序服务从持久性加载之后,必须将该信息作为原始值或值对象传递给Aggregate。
答案 1 :(得分:1)
但我对域服务是域模型中的类,接口或方法以及我的聚合根/域实体如何调用该服务感到困惑?
域服务可以是实现某些接口的对象,例如具有具体实现对象的IShippingCostCalculator,例如Company1ShippingCostCalculator和Company2ShippingCostCalculator。域服务可以从域模型(聚合,实体)或应用服务调用。
如果我的聚合根需要检查电子邮件是否存在,或者检查密码哈希匹配(需要调用服务/存储库来访问数据库)。我是否需要在域服务或应用程序服务中实现该代码? / p>
对于需要某些HTTP调用的外部服务或任何其他,您必须在域中具有接口并在某些基础架构方面实现,并使用DI注入具体实现。例如,Domain Layer中的IEmailSender接口和域外的EmailSender实现。 Application Services仅用于域模型协调(Orchestration)。
答案 2 :(得分:0)
:服务总是作为接口公开,而不是出于可交换性,可测试性等目的,而是以合同的形式公开一组内聚的操作。除了这种含意之外,通常还包括无状态的假设以及根据GRASP进行的纯制造思想。阅读更多here