“极客时间”《DDD 实战》课程笔记 (四)DDD与微服务代码编写

发表于2020-02-24,长度2325, 129个单词, 6分钟读完
Flag Counter

这是一系列学习笔记,对象是 极客时间 上面的收费课程 《 DDD实战 》。前面的笔记介绍了领域和微服务的关系,这一篇记录一下和代码相关的知识点。

其实极客上面的课程里还有中台相关的几讲,不过我理解不深没法做出笔记;另外还有一讲是讲DDD实践的事件风暴的,这里不记录了,可以参考以前的博客《领域驱动设计DDD入门7:加速工具和管理工具

按照 DDD 分层架构模型设计出来的微服务代码模型是什么样子呢?

DDD 并没有给出标准的代码模型,不同的人可能会有不同理解。下面要说的这个微服务代码模型是欧老师经过思考和实践后建立的,主要考虑的是微服务的边界、分层以及架构演进。

一级目录

顶层目录分别是按照四层对应过来的,用户接口层、应用层、领域层、基础层分别对应interfaces、application、domain 和 infrastructure 四个一级代码目录:

Interfaces(用户接口层)

主要存放与前端交互、展现数据相关的代码。前端应用通过这一层向应用服务获取展现所需的数据。

这一层主要用来处理用户发送的 Restful 请求,解析用户输入的配置文件,并将数据传递给 Application 层。数据的组装、数据传输格式以及 Facade 接口等代码都会放在这一层目录里。

Application(应用层)

主要存放应用层服务组合和编排相关的代码。应用服务基于微服务内的领域服务或外部微服务的应用服务完成服务的编排组合,向上为用户接口层提供支持服务。

应用服务和事件等代码会放在这一层目录里。

Domain(领域层)

主要存放核心业务逻辑相关的代码。领域层可以包含多个聚合代码包,它们共同实现领域模型的核心业务逻辑。聚合以及聚合内的实体、方法、领域服务和事件等代码会放在这一层目录里。

Infrastructure(基础层)

主要存放基础资源服务相关的代码,为其它各层提供的通用能力、三方包、数据库服务、配置和基础资源服务的代码在这一层目录里。

二级目录

用户接口层

Interfaces 的代码目录结构有assembler、dto 和 façade 三类:

Assembler:实现 DTO 与领域对象之间的相互转换和数据交换。一般来说 Assembler 与 DTO 总是一同出现。

Dto:它是数据传输的载体,内部不存在任何业务逻辑,我们可以通过 DTO 把内部的领域对象与外界隔离。

Facade:提供较粗粒度的调用接口,将用户请求委派给一个或多个应用服务进行处理。

应用层

应用层包括event和sevice:

Event(事件):这层目录主要存放事件相关的代码。它包括两个子目录:publish 和 subscribe。前者主要存放事件发布相关代码,后者主要存放事件订阅相关代码(事件处理相关的核心业务逻辑在领域层实现)。

虽然应用层和领域层都可以进行事件的发布和处理,但为了实现事件的统一管理,建议将微服务内所有事件的发布和订阅都统一放到应用层,事件相关的核心业务逻辑实现放在领域层。通过应用层调用领域层服务。

Service(应用服务):这层的服务是应用服务。应用服务会对多个领域服务或外部应用服务进行封装、编排和组合,对外提供粗粒度的服务。应用服务主要实现服务组合编排,是一段独立的业务逻辑。

可以将所有应用服务放在一个应用服务类里,也可以把每一个应用服务设计为一个应用服务类

领域层

Domain 是由聚合构成,共同实现领域模型的核心业务逻辑。聚合内的代码模型是标准和统一的,包括:entity、event、repository 和 service 四个子目录。

Aggregate(聚合):它是聚合软件包的根目录,可以根据实际项目的聚合名称命名,比如权限聚合。在聚合内定义聚合根、实体和值对象以及领域服务之间的关系和边界。聚合内实现高内聚的业务逻辑,它的代码可以独立拆分为微服务。

以聚合为单位的代码放在一个包里的主要目的是为了业务内聚,而更大的目的是为了以后微服务之间聚合的重组。聚合之间清晰的代码边界,可以让你轻松地实现以聚合为单位的微服务重组,在微服务架构演进中有着很重要的作用。

Entity(实体):存放聚合根、实体、值对象以及工厂模式(Factory)相关代码。实体类采用充血模型,同一实体相关的业务逻辑都在实体类代码中实现。跨实体的业务逻辑代码在领域服务中实现。

Event(事件):存放事件实体以及与事件活动相关的业务逻辑代码。

Service(领域服务):一个领域服务是多个实体组合出来的一段业务逻辑。领域服务封装多个实体或方法后向上层提供应用服务调用。

Repository(仓储):存放所在聚合的查询或持久化代码,通常包括仓储接口和仓储实现方法。为了方便聚合的拆分和组合,我们设定了一个原则:一个聚合对应一个仓储。

按照 DDD 分层架构,仓储实现本应该属于基础层代码,但为了在微服务架构演进时,保证代码拆分和重组的便利性,就把聚合仓储实现的代码放到了聚合包内。

基础层

Infrastructure 的代码目录结构有:config 和 util 两个子目录。

Config主要存放配置相关代码;Util主要存放平台、开发框架、消息、数据库、缓存、文件、总线、网关、三方类库、通用算法等基础代码,你可以为不同的资源类别建立不同的子目录。

总结

第一点:聚合之间的代码边界一定要清晰。在以后业务发展和需求变更时,可以很方便地实现业务功能和聚合代码的重组,在微服务架构演进中将会起到非常重要的作用。

第二点:一定要有代码分层的概念,搞清楚代码的职责,将它放在职责对应的代码目录内。如果将核心领域逻辑代码放到应用层,微服务慢慢就会演变成传统的三层架构模型了。

Written on February 24, 2020
分类: dev, 标签: ddd
如果你喜欢,请赞赏! davelet