DDD领域驱动战略篇(4)
架构与代码模型
认识分层架构
分层架构是运用最为广泛的架构模式,几乎每个软件系统都需要通过层来隔离不同的关注点,以此应对不同需求的变化,使得这种变化可以独立进行
传统经典三层架构
DDD经典分层结构
用户界面/展现层:负责向用户展现信息以及解释用户命令
应用层:很薄的一层,用来协调应用的活动,它不包含业务逻辑,它不保留业务对象的状态,但它保有应用任务的进度状态
领域层:本层包含关于领域的信息,这是业务软件的核心所在。在这里保留业务对象的状态,对业务对象和它们状态的持久化被委托给了基础设施层
基础设施层 :本层作为其他层的支撑库存在。它提供了层间的通信,实现对业务对象的持久化,包含对用户界面层的支撑库等作用
分层的依据和原则
基于关注点为不同的调用目的划分层次:以领域驱动设计的四层架构为例,之所以引入应用层就是为了给调用者提供完整的业务用例
面对变化:针对不同的变化原因确定层次的边界,严禁层次之间互相干扰
保证同一层的组件处于同一个抽象层次
层与层之间协作
依赖倒置原则:我们要依赖不变或稳定的元素(类、模块或层),抽象不应该依赖于细节,细节应该依赖于抽象
低层模块的细节实现可以独立变化,避免变化对高层模块产生污染
在编译时,高层模块可以独立于低层模块单独存在
对于高层模块而言,低层模块的实现是可替换的
为了更好地解除高层对低层的依赖,我们往往需要将依赖倒置原则与依赖注入结合起来
分层架构的演化
整洁架构
该架构思想提出的模型并非传统的分层架构,而是类似于一个内核模式的内外层架构,由内及外分为四层
层次越靠内的组件依赖的内容越少,处于核心的 Entities 没有任何依赖
层次越靠内的组件与业务的关系越紧密,因而越不可能形成通用的框架
Entities 层封装了企业业务规则,准确地讲,它应该是一个面向业务的领域模型
Use Cases 层是打通内部业务与外部资源的一个通道,因而提供了输出端口(Output Port)与输入端口(Input Port),但它对外的接口展现的其实是应用逻辑,或者说是一个用例
Gateways、Controllers 与 Presenters 其本质都是适配器(Adapter),用于打通应用业务逻辑与外层的框架和驱动器,实现逻辑的适配以访问外部资源
系统最外层包括框架和驱动器,负责对接外部资源,不属于系统(仅指限界上下文而言)开发的范畴,但选择这些框架和驱动器,是属于设计决策要考虑的内容。这一层的一些组件甚至与要设计的系统不处于同一个进程边界
六边型架构
六边形架构在满足整洁架构思想的同时,更关注于内层与外层以及与外部资源之间通信的本质:六边形架构通过内外两个六边形为系统建立了不同层次的边界。核心的内部六边形对应于领域驱动设计的应用层与领域层,外部六边形之外则为系统的外部资源,至于两个六边形之间的区域,均被 Cockburn 视为适配器(Adapter),并通过端口(Port)完成内外区域之间的通信与协作,故而六边形架构又被称为端口-适配器模式
下面是对六边型架构的一个落地实践示例:
六边形架构中,Gateways、Controllers 与 Presenters 统一看做是适配器
不同的命名代表的是对其职责认识上的不同,如果认为是“网关”,则将该组件的实现视为一种门面,内部负责多个对象之间的协作以及职责的委派;如果认为是“适配器”,则是为了解决内外协议(数据协议与服务接口)之间的不一致而进行的适配。
微服务架构
下图的逻辑边界代表了一个微服务
该架构图并未严格按照分层架构模式来约定各个组件的位置与职责,这是完全合理的设计
整幅图的架构其实蕴含了两个方向:自顶向下和由内至外
Resource(REST服务中资源层的意思) 组件就是我们通常定义的 Controller,对应于上下文映射中的开放主机服务
当微服务需要调用外部服务,且外部服务由 HTTP 协议通信,就需要提供一个 HTTP Client 组件完成对外部服务的调用
为了避免当前微服务对外部服务的强依赖,又或者对客户端的强依赖,需要引入 Gateways 来隔离,充当防腐层
领域驱动架构的演进
改良的DDD经典分层
将基础设施层奇怪地放在了整个架构的最上面
整个架构模型清晰地表达了领域层别无依赖的特质,但整个架构却容易给人以一种错乱感
这个架构模型仍然没有解决人们对分层架构的认知错误,例如它并没有很好地表达依赖倒置原则与依赖注入
这个架构模型将基础设施层放在了整个分层架构的最顶端,导致它依赖了用户展现层
那如何继续演进呢ÿ