文章目录
笔者从业以来,从 MVC 入门再到接触 DDD 架构,落地 DDD 项目。学习到关于 DDD 的各种优势、特别是针对复杂业务上。例如:
- 拒绝贫血模型,工程上真正面向对象设计,通过充血模型将数据和行为绑定。
- 业务优先、代码能够准确表达业务逻辑,代码即设计,方便维护,提高可读性
- 分而治之、领域驱动的战略设计,帮助我们通过边界划分复杂业务领域
- 统一语言,领域知识共享,提高沟通协作效率
笔者近期发现一些开发对 DDD 认识不甚了解,或者觉得只是“形式”,真正落地的少之又少。我认为这是缺乏深入思考和总结导致的。对于领域驱动开发,我认为战略意义要大于战术落地,对于大多数后端开发来说,具备领域驱动的思维才是入门架构师的第一步。
本文不深入讨论 DDD ,主要总结从 MVC 、DDD、Hexagon、Onion、Clean等等架构演进的历史。
一、MVC架构
这是很多后端开发梦开始的地方,主要解决的问题是把用户界面和业务逻辑分离。那个年代懂设计模式就可以称为架构师。
二、N-Layered N层架构 2002 – Martin Fowler
核心思想是代码分层,分层的依据是代码的相关性。例如用户界面、业务逻辑、数据库操作等。
层的数量并没有要求,大多数业务三层就够了,但是要求层与层直接有明确的单向依赖关系。
实现上可以通过目录或者模块的方式进行分层,或者是二者的结合。但是通过模块的方式能够使层级间的依赖关系更加明确。
每层通过接口访问下一层,看起来非常熟悉,分层思想也一直延续到后续的架构演进。但是随着软件复杂性的提升,业务逻辑层逐渐庞大、难以良性维护下去。
三、DDD 领域驱动设计 2003 – Eric Evans
重点是将业务逻辑的核心问题单独抽取出领域层,领域模型作为通用语言,是各方沟通的基础,也可以作为服务拆分的依据;
将数据库、及缓存、短信推送等等划到基础设施层;
应用层只负责组合相关领域模型等,告别臃肿的 Service 层
四、Ports and Adapters 六边形架构 2005 – Alistair Cockburn
相比于传统的 DDD
- 通过依赖反转的原则,让业务逻辑不再依赖具体的基础设施实现。Domain 真正成为系统的核心组件( Core ),不再依赖其他项目。
- Infra 被分为两个部分,抽象(接口)和实现。抽象成为业务逻辑(Core)的一部分,被称为端口(Ports);实现部分保留在 Infra 层,称为适配器(Adapters),和 UI 在同一个框架层。
- 将基础设施的接口放在 Domain 中,使 Domain 变得自治无依赖。例如要改变数据库,只需要变更实现部分,实现所需的适配器,将其“插入”到可用的端口中。不影响 Domain 层的业务逻辑和接口。
Domain 层变得更加内聚、清晰。
调用 Core 的适配器称为主要适配器(驱动),被核心逻辑调用的称为次要适配器(被驱动)
五、Onion 洋葱架构 2008 – Jeffrey Palermo
将 DDD 提出的应用层加入六边形,形成洋葱架构,其核心思想是:任何外层只能依赖于内层。
意义在于将经常变更的逻辑放在外层,外层变更不影响内层。
六、Clean 整洁架构 2012 – Robert C.Martin
相比于洋葱架构:
- 将 Domain 替换为 Entities (实体),并且实体不再只是领域服务和贫血模型,而是拥有数据和行为的充血模型。
- 以 Use Cases 替换应用层,并将原 Domain 中的数据库、UI等端口(接口)移到了 Use Cases 层。
- 最外层增加一层,包含增加了框架、DLL 和其他外部依赖等。
- 内层同样不能依赖外层。
右边小图黑线表示表面上的用户请求过程中的系统交互
绿线表示实际上的端口(接口)调用
橙线表示实际的实现层。
总结
以上仅列举部分比较有名的架构,这些架构在细节上存在差异,但目标是一致的,即职责分离。最终要实现的就是“低耦合高内聚”。
业务的演进才是推动架构发展的动力,这是对技术内功的挑战,也让我们持续学习的动力。