前言
DDD架构分层由内到外主要分为domain层->application层->infrastructure层->interface层
其中领域服务属于domain层、应用服务属于application层,领域服务的实现和application的实现都在infrastructure层。
应用服务没有领域逻辑,仅仅是对领域层case的编排,比如先调a再调b,这种case流
领域服务包含业务逻辑,那么包含哪些业务逻辑就是我们今天讨论的主题。
领域服务的业务逻辑
1、什么时候使用领域服务
- 执行一个显著的业务过程
- 对领域对象进行转换
- 以多个领域对象作为输入进行计算,结果产生一个值对象
以上说法来自于实现领域驱动设计,那么我们自己的理解呢?
2、实践过程中引入领域服务
- 在落地领域驱动设计的时候我们常常会遇到这种困惑,即在一个聚合中想要引用另一个聚合,然后两个聚合合作完成一个业务过程。
这个时候如果我们从聚合角度出发会产生三种想法:
a、在聚合A中引入聚合B的Repository
b、在聚合A的方法中以入参形式引入聚合B
c、直接在聚合A中组合聚合B
第一种和第三种有违领域驱动设计初衷,第二种虽然可行,但是语义上会存在不通顺的情况。所以,在我们遇到以上三种情况的困惑是领域服务就是我们的解药。 - 对于同一种聚合,如聚合A,有多个聚合A的实例,实际上就是多个聚合,只不过聚合的class类相同。这种多聚合合作也需要引入领域服务。领域服务以多个聚合作为入参,最后通过聚合完成业务逻辑。
3、避免贫血模型
- 过度的使用领域服务会导致贫血领域模型,业务逻辑尽量写到聚合和值对象中
- 有些情况下我们会逼不得已使用领域服务完成一个“显著”的业务过程,这个显著的业务过程会非常“厚”。此时我们应该提高警惕,是不是领域限界上下文划分错误,导致一些不属于领域限界上下文的聚合被建模进来。
4、领域服务代码设计
- 领域服务尽量只依赖Aggregates去完成领域事件,通过Application层从repo获取聚合注入进来,此时领域服务的实现位于领域层
- 次之,需要调用其他上下文的服务来完成领域事件,此时需要明确建立“防腐层”,使用依赖倒置,在领域层定义接口,在infrastructure层定义实现
- 除此之外,领域服务不应该通过调用外部来收集数据执行逻辑,这些应该属于应用服务
总之,领域服务尽量避免写太多业务逻辑,导致贫血模型产生。