实现领域驱动设计-领域服务

领域服务定义

先看看领域服务的定义:领域中的服务表示一个无状态的操作,它用于实现特定于某个领域的任务。当某个操作不适合放在聚合(实体)或值对像上时,最好的方式便是使用领域服务。书中说,有时我们倾向于使用聚合根上的静态方法来实现这些操作,但是在DDD中,这是一种坏味道。

可以大概理解出三个特征:

1、强调一个无状态的操作,状态应该在实体中维护,领域服务处理是无状态的逻辑过程;

2、实现某个领域的任务,即做的也是领域内的事情,是通用语言的表达。而不是应用服务,应用服务是领域服务的客户方,比如api聚合服务,不应该做领域内的事情。也不是基础设施服务,比如DB或消息基础组件。特别是不能跟现在常用的mvc+s架构中的s(service)层混淆,这种情形下的s,很多时候是持久层接口组装,更像是DDD中的资源库的概念。

3、先考虑聚合或值对像的建模,不适合,然后才使用领域服务。聚合(实体)和值对像才是最重要的DDD建模对象,如果反而首先使用领域服务,容易导致“贫血领域模型”。既然不适合直接在实体或值对像上建模,也基本说明很多时候涉及到多个实体或值对像。

可以再展示一下第4章架构中的提到的典型的DDD分层架构:领域服务是位于领域层的


DDD经典分层架构

那什么时候该使用领域服务呢,书中提了三点:

1.执行一个显著的业务操作过程

2.对领域对象进行转换

3.以多个领域对象作为输入进行计算,结果产生一个值对像

基本就是跟上面对领域服务概念的理解是一致的。

领域服务实现

是否需要独立接口?

优点:使用接口表达领域概念,而技术实现可以比较随意,比如放在基础实施层,或者在依赖倒置原则中,放在应用层实现也可以;独立接口有利于解耦,通过依赖注入或工厂可以完全解耦客户端与具体实现;

缺点:得写两个对象代码,特别对于java,还得分两个文件,阅读代码也增加点难度,而很多时候一个接口也只有一个实现;另外一个命名问题,在DDD中领域对象名称(对应语言实现的类)和操作名称(对应函数名)是很重要的,是需要表达通用语言的概念的。但如果定义独立接口,也就是会XXXservice的名字来定义接口,但服务实现用什么命名呢?如果用XXXserviceImpl,那其实也说明可以不需要定义独立接口了。

测试领域服务

其实测试方面,我觉得没有很多需要关注的,或者说我比较少测试方面的需要。但在测试领域服务一节有句话却比较有意思“我们希望对领域服务进行测试,并且希望从客户端的角度对领域服务进行建模,同时我们希望测试能够反映查领域服务的使用方式”,即通过测试代码,告诉客户端怎么使用领域服务。这其实是测试代码的一个重要的作用,但也经常被我们忽略的。

问题

在P250中有句话不理解,记录如下“在应用服务中,我们关心的是事务和安全,但是这些不应该出现在领域服务中”,这里的事务是指什么?怎么会是应用服务来关心事务,如果是数据库事务之类,那肯定不应该又应用服务来关心,而应该是资源库。后续找一下英文原版对照解读下

你可能感兴趣的:(实现领域驱动设计-领域服务)