天天看点

领域驱动设计-从分层架构聊起

一、概述

对于比较复杂的业务流程,传统的分层架构等在后续代码可扩展性,可维护性,可测试上存在很大的问题,最近也在学习和研究领域模型相关的设计,实践总结一下。

代码仓库:Jmqtt,只关注其中的jmqtt-admin模块即可,欢迎老铁给个star

二、传统的分层架构

如图:

领域驱动设计-从分层架构聊起

这是一个极简的三层架构模式,每层的关系和职责大约是:

  • WEB层(Controller层):提供http接口给外部,处理参数的接收和响应;依赖业务层;与之类似的层包括:Gateway层,OpenAPI层,服务层(提供RPC给其他服务)等
  • 业务层(Service层):负责处理业务逻辑,包括参数校验,数据处理转换,业务逻辑处理,与数据层交互等;依赖数据层
  • 数据层(DAO层):负责处理数据持久化,数据缓存等;与之类似的层包括:整合层(基础依赖层,处理MQ,定时任务等基础依赖),外部依赖层(依赖其他服务提供的RPC服务接口,http接口等服务)
  • 通用层:工具类等处理

三、领域驱动设计的六边形架构

领域驱动设计-从分层架构聊起

六边形架构网上已经有很多解释和说明了,这里我说下我的理解:

  • 领域层(domain层):处理领域模型的地方,在领域设计中的实体,值对象,领域服务,聚合根,聚合等都放在这里。不依赖任何外部模块,提供接口(adapter)给外部实现进行交互。
  • 应用层(application层):依赖领域层,可对标三层架构中的业务层进行理解,不过领域设计中的应用层只负责业务流程编排,不负责数据完整性校验,业务逻辑处理等。依赖领域层,调用领域层的领域服务或聚合根进行业务编码
  • 数据层(dal层):处理数据持久化的逻辑,实现领域层的adapter接口,依赖领域层。
  • 整合层(intergration层):处理外部依赖,包括其他服务提供的RPC服务,外部Http接口服务等,实现领域层adapter接口,依赖领域层。这里还有一层防腐层(ACL),主要是处理对第三方依赖的强依赖,防止因第三方服务不可用或服务接口数据改动,导致领域服务不可用。
  • 基础依赖层(intergration层):处理MQ,定时任务等基础依赖,可与整合层放在一起,主要处理第三方中间件依赖等,实现领域层的adapter接口,依赖领域层。
  • 接口服务层(facade/client层):主要暴露对外提供的接口服务,封装DTO,CQRS,领域事件对象等,不依赖任何外部服务,领域层依赖该模块,放在这里主要是为了说明。
  • 测试层(test层):主要负责单元测试和集成测试,依赖所有层,放在这里主要是为了说明。

其它还没标明的一些层:

  • WEB层(controller层):依赖领域层,提供http接口服务,其它类似Gateway层等
  • 通用层(common层):各层的工具在各层自行封装,降低依赖。也可以引入一个通用Common层,比如日志处理等。

四、实践案例

背景:jmqtt-admin是一个iot mq的管理平台,背景主要是提供Iot设备的管理,监控,数据采集等。

下面是jmqtt-admin的模块设计:

领域驱动设计-从分层架构聊起

目前代码整个管理平台还在开发中,整套后端代码会采用领域设计的方式开发,欢迎持续关注,

附模块依赖图:

Gateway依赖WEB层,可复用WEB层的拦截器等进行处理。

领域驱动设计-从分层架构聊起

五、聊聊区别

分层架构:

  • 一般是数据建模渠道,接到业务需求后,技术手段上首先是进行数据建模,再进行开发。
  • 重业务层,一般没有领域的概念,重业务层意味着基本所有核心业务都是在业务层解决的,对下直接依赖数据层,数据层上一般是提供接口和数据DO对象,导致切换底层数据源时,上层业务层可能也需要做一些改动(耦合高)。同理,改动业务层也可能涉及底层依赖的改动
  • 扩展比较难:每次改动都需要改动业务层,若业务复杂,可能一个方法里包含了非常多的逻辑,包括:验参,处理业务逻辑,请求第三方依赖获取数据,数据转换,数据持久化等等
  • 较难测试:对于一个业务,往往业务大了,想要测试这个业务方法时,需要将业务逻辑依赖的所有服务都启动起来,单测比较麻烦。

领域驱动设计:

  • 表现为领域驱动设计:由技术专家+业务专家共同建模(梳理业务流程,对焦通用语言,划分领域边界),技术上表现先开发领域层,定义领域模型和接口服务,再开发其他具体实现
  • 重领域层,核心变动和经常改变的应该都是在领域层,其他层变动不应该影响领域层,领域层的变动应该只影响上层应用层。领域层的实体除了负责简单数据属性外,还要处理业务逻辑
  • 较为复杂,需要和前期学习成本:如图,比较复杂。在前期业务简单时,开发速度比分层架构慢,但是后续可扩展性和可维护性及可测试行强很多(领域模型区分了变化与不变的边界。频繁变化的逻辑应该都在领域层)
  • 不一定适用所有业务应用,不过领域划分的思想适合用来划分微服务,约束相关开发,一旦形成约定,对于代码理解成本也会降低一些。