领域对象与微服务代码对象的映射
完成上面的分析和设计后,即可建立像下图一样的,领域对象与微服务代码对象的映射关系了。
个人客户领域模型中的个人客户聚合,就是典型的领域模型,从聚合内可以提取出多个实体和值对象以及它的聚合根。该图个人客户聚合做了进一步的分析。提取了个人客户表单这个聚合根,形成了客户类型值对象,以及电话、地址、银行账号等实体,为实体方法和服务做了封装和分层,建立了领域对象的关联和依赖关系,还有仓储等设计。
这个过程建立了领域对象与微服务代码对象的映射。
- 层
定义领域对象位于分层架构中的哪一层。比如:接口层、应用层、领域层以及基础层。 - 领域对象
领域模型中领域对象的具体名称。 - 领域类型
根据DDD知识体系定义的领域对象的类型,包括:限界上下文、聚合、聚合根、实体、值对象、领域事件、应用服务、领域服务和仓储服务等领域类型。 - 依赖的领域对象
根据业务对象依赖或分层调用的依赖关系,建立的领域对象的依赖关系,比如:服务调用依赖、关联对象聚合等。 - 包名
代码模型中的包名,对应领域对象所在的软件包。 - 类名
代码模型中的类名,对应领域对象的类名。 - 方法名
代码模型中的方法名,对应领域对象实现或操作的方法名。
在建立这种映射关系后,我们就可以得到如下图的微服务代码结构了。
非典型领域模型
有些业务场景可能并不能如你所愿,你可能无法设计出典型的领域模型。这类业务中有多个实体,实体之间相互独立,是松耦合的关系,这些实体主要参与分析或者计算,你找不出聚合根,但就业务本身来说它们是高内聚的。而它们所组合的业务与其它聚合是在一个限界上下文内,你也不大可能将它单独设计为一个微服务。
这种业务场景其实很常见。比如,在个人客户领域模型内有客户归并的聚合,它扫描所有客户,按照身份证号码、电话号码等是否重复的业务规则,判断是否是重复的客户,然后对重复的客户进行归并。这种业务场景你就找不到聚合根。
那对于这类非典型模型,我们怎么办?
我们还是可以借鉴聚合的思想,仍然用聚合来定义这部分功能,并采用与典型领域模型同样的分析方法,建立实体的属性和方法,对方法和服务进行封装和分层设计,设计仓储,建立领域对象之间的依赖关系。唯一可惜的就是我们依然找不到聚合根,不过也没关系,除了聚合根管理功能外,我们还可以用DDD的其它设计方法。
FAQ
- 领域类,有领域异常吧?比如我有一个背包聚合,扣减背包库存的时候,可能抛出库存不够的异常,这种异常也是要定义在领域层。
- 如果我有两个微服务, 查询场景下, 服务A需要调用服务B去获取服务B中聚合的一个值对象(Z.class),对于在服务A中,从服务B里拿来的这个值对象也同样是当值对象使用并绑定在服务A的一个聚合对应的DTO里, 请问服务A是否能直接使用服务B包中的Z.class,还是说需要在A服务中重新创建一个相应的Class以起到防腐层的效果?
都两个微服务了,在两个不同的项目里,要重建一个新的值对象的class的。