「尺有所短,寸有所长;不忘初心,方得始终。」
一、传统分层架构
程序分层并不陌生,分层能够使程序各层专注自己功能的实现,便于代码复用与程序扩展。分层架构的「一个重要原则是每层只能与位于其下方的层发生耦合」。最常见的就是传统的三层结构:接口层、业务层、和基础设施层。
「接口层」
主要是API的定义,包括资源路径定义、请求报文接受、响应报文返回、请求编码等定义的内容。
「业务层」
主要做业务核心逻辑编写,组合不同数据仓库,组件等做业务逻辑。
「数据访问层」
主要做数据存储,数据接口的定义,映射XML的编写。
有上图可以看出来,
上层对于下层有直接的依赖关系,导致耦合度过高。 业务层中填充了大量业务逻辑,耦合了消息队列,缓存,第三方工具,通用算法等,是一个非常臃肿的状态,当我们业务增多或者非常复杂的时候,业务层就会非常庞大,难以维护。
二、DDD分层架构
DDD的分层架构理念源于整洁架构的思想,在具体实践中一共提供了四层架构,五层架构,六边形架构分层架构的指导思想,而在DDD的落地中使用的比较多的就是四层架构,有时候也称之为经典四层架构。
2.1 整洁架构
「在领域驱动设计的分层架构中,对传统的自上而下的依赖提出了挑战。采用依赖倒置原则:」
要求高层模块不应依赖于底层模块,二者都应依赖于抽象。 抽象不应该依赖于细节,细节应该依赖于抽象。
基于此,「我们不能再用传统MVC的上下层的一维思想去看待DDD的四层架构,而应该以水平的二维眼光去看待。」
「整洁架构模型」
整洁架构:又称为「干净架构」,有时也称为「洋葱架构」,它是「在水平的二维上进行分层,类似于一个内核模式的内外层架构」,由内及外分为四层。每层仅「取决于直接位于其内部的层」。最独立的层显示在最内圈,属于领域层。
越靠内的层组件依赖的内容越少,处于核心的 Entities 不依赖与任何层。 越靠内的层组件与业务的关系越紧密,具有业务唯一性。 领域服务层封装了业务规则,是一个面向业务的领域模型。 应用服务层是内部业务与外部资源的一个隔离,它对外展现其应用逻辑,对内进行业务编排。 用户界面实现应用业务与外层框架和驱动器的交互,给外部资源提供访问的入口。 基础资源负责对接外部资源,BD,缓存,中间件等。
2.2 DDD四层架构
2.2.1 DDD四层概述
在《领域驱动设计——软件核心复杂性应对之道》中Eric Evans为应用架构划分了「用户界面层,应用层,领域层,基础设施层」四个层级并使用一张图描述了层与层之间的关系:
通过这张关系图可以看出在DDD的分层中「是存在跨层调用的,即用户界面层可以调用应用层、领域层,基础设施层,这种设计在一定程度上无法起到层与层之间隔离作用,是否采用可以根据自己的实际情况取舍,不过我在实践中并没有使用这种方式。」
2.2.2 四层架构结构模型
DDD的四层架构与整洁架构的架构模型表现形式虽然不一样,但是它们「以领域模型为中心的设计思想」正是「微服务架构高内聚低耦合原则」完美体现。
「用户界面层」
当服务应用面向多个前端应用时,可能由于渠道而导致数据的返回不同,为保证核心业务逻辑不暴露,防止数据外泄,也为提高应用服务或领域服务的复用性与扩展性。用户界面层为前端应用提供不同的服务适配,保证应用层和领域层核心领域逻辑的稳定。
封装应用服务,适配不同前端应用,提供不同类型的服务接口。 根据前端应用的要求,完成数据的组装和转换。 「应用层」
应用层用户隔离用户接口层和领域层 「主要用于协调领域服务和领域对象完成组合、编排和转发,处理执行结果的拼装。」 「远程的服务调用、安全认证、权限校验、事务控制、领域事件发布或订阅等都在应用服务中进行。」 「领域层」
领域层实现领域模型的核心业务逻辑,是领域模型的核心。
领域模型的业务逻辑主要由「实体(充血模型)和领域服务」来实现。
「当单一实体或值对象不能实现时,就由领域服务进行组合和协调聚合内多个实体或值对象,实现复杂的业务逻辑。」
「基础设施层」
基础层贯穿DDD所有层,提供通用的技术和基础服务,为应用层传递消息,为领域层提供持久化机制。「基础设施层采用依赖倒置的设计思想,与其他层解耦。」
第三方工具、驱动、消息中间件、网关、文件、缓存、数据库等。
三、MVC三层架构与DDD四层架构的演变
DDD四层架构「并非」是字面上在MVC三层架构上加一层,两者最大的区别:
「思想上的转变」
MVC三层架构是上下层设计思想 DDD四层架构一个内核模式的内外层架构 「各层自己的职责重新划分」
「用户接口层」
封装应用服务,给前端应用提供灵活的数据和接口适配能力。
「业务逻辑层」
「业务逻辑层拆分到应用层和领域层,应用服务实现服务的组合和编排,领域服务完成核心领域逻辑。」
「数据访问层」
数据访问层从DAO方式改为「仓储模式,领域层可以用过仓储接口访问基础资源的实现逻辑。」