交易|微服务与领域驱动设计,架构实践总结( 二 )


解决过相关业务场景的研发都知道 , 重构加持续集成能力 , 结合严谨的测试 , 可以应对业务的不断变化;但是在版本兼容的过程中 , 依然会导致工程中的代码膨胀到飞起 , 特别是出现中场换人的情况 , 都会让接手的人员在被埋和离开中 , 产生一次剧烈的心态挣扎 。
3、问题分析在MVC的架构模式中 , 工程通常会进行如下的分层管理:控制层、服务层、持久层、存储层;服务层在特定复杂的场景中会做细化拆分 , 比如第三方对接、常用中间件的二次封装:

对于在复杂业务线上争渡的选手来说 , 对Mvc分层模式的缺陷是深有体会的 , Service层聚焦大量复杂的逻辑 , 通常核心业务块中总会存在几个代码过千行的实现逻辑 , 不管用什么思路和模式去拆分封装 , 都很难解决该层不断扩展带来的膨胀问题 。
4、面向过程在MVC分层中 , 过程式的代码极其明显 , 通常以数据库表和关系为基础 , 映射构建相关实体对象 , 这些实体对象并没有具体的行为和逻辑 , 只是作为数据和结构的载体:

从面向对象中类的定义去看:属性和行为;而在MVC模式中 , 绝大多数实体都只是作为数据的入参出参的结构定义 , 可以理解为数据容器 , 在MVC的各层之间不断搬运和加工 。
三、领域驱动设计相比MVC的分层设计 , 领域驱动设计(Domain-Driven-Design简称DDD)对于复杂业务系统的实现 , 提出了更加合理的解决方案 , DDD模式中涉及大量专业术语和抽象概念 , 可以参考EricEvans的相关书籍 , 本文只描述实践中的核心概念 。
1、分离模式DDD模型在分层设计上 , 划分出核心的四层:接入层、应用层、领域层、基础设施层;注意这里只是单纯站在服务端的常规架构角度去看 , 很明显分离MVC模式中的服务实现层的逻辑:

其中领域层是关键所在 , 用来封装复杂的业务 , 对应用层提供业务管理的核心支撑;整个模型也更具备纵向思维 , 有效地缓解单层复杂度过高的现象;单从模型设计上看 , 在工程中基于该分层去管理代码包 , 也可以使每层的设计更加清晰和独立 。
2、设计思想领域驱动设计并不是简单的分层管理模型 , 涉及诸多抽象逻辑与专业术语 , 例如:领域、界限上下文、实体、聚合、值对象等等;
2.1 领域
领域可以理解为业务场景中需要解决的问题合集 , 是具有范围和边界的约束;领域可以拆分为多个子域 , 通常描述为:核心域、支撑域、通用域:

关于子域的划分也是参考业务属性 , 可以把核心域理解为最关键的业务场景 , 并且需要资源倾斜以应对其不断地发展;支撑域可以理解为相对稳定的业务;通用域偏向系统架构层面的公共能力;通过对领域的拆分实现业务分治 , 这与微服务的拆分思想相符合 , 两种模式在业务角度是比较统一的;
2.2 界限上下文
DDD中最晦涩难懂的一个抽象概念 , 特定模型的限界应用 , 不过可以借用原文的比喻会意一下:细胞之所以能够存在 , 是因为细胞膜限定了什么在细胞内 , 什么在细胞外 ,并且确定了什么物质可以通过细胞膜:

界限上下文的定义涉及粒度的思想 , 即每个粒度要具备独立性;如上图仓储业务 , 可以将服务部署与仓储子域、仓储上下文做成一一对应的关系 , 或者在仓储子域中分别定义:仓库和货架两个上下文;这里具有极大的灵活性 , 没有真正意义上的标准可以参考 。
2.3 映射关系
做好界限上下文的划分 , 理清各个上下文之间的关系 , 明确业务场景中的依赖顺序 , 这样可以更好地推动开发流程的落地;对于上下文的关系描述也远不止图中的这些 , 还有共享内核、合作等等:

  • 上下游(U-上游 , D下游):描述上下文调用时的关系 , 服务调用方为D , 服务提供方为U;
  • 防腐层(Anticorruption-Layer , 简写ACL):上下文交互时封装的一层 , 提供对动作的校验、适配、转换等;
  • 开放主机服务 , 发布语言(Open-Host-Service简写OHS , Published-Language简写PL):定义访问协议;
在上下文交互时 , 防腐层可以维护上下文的隔离和独立 , 确保调用方不直接依赖服务提供方 , 从而实现不同上下文之间的依赖解耦;同时这也会带来大量的对象转换动作;
2.4 建模设计
子域和界线上线文完成对业务的拆分切块 , 从而进行分治;基于防腐层降低各个界限上下文的耦合程度;聚合思想保证了业务问题的解决方案内聚;严格的分层模型实现服务支撑能力的分散;