DDD - 领域驱动设计分层架构:构建可演化的微服务架构

ops/2025/2/1 15:08:24/

文章目录

  • 引言
  • 1. 什么是DDD分层架构
    • 1.1 DDD分层架构的演变
    • 1.2 四层架构的起源与问题
    • 1.3 依赖倒置和五层架构
  • 2. DDD分层架构的核心层次
    • 2.1 用户接口层(User Interface Layer)
    • 2.2 应用层(Application Layer)
    • 2.3 领域层(Domain Layer)
    • 2.4 基础层(Infrastructure Layer)
  • 3. DDD分层架构的重要原则
    • 3.1 严格分层架构 vs 松散分层架构
    • 3.2 依赖倒置原则(DIP)
  • 4. DDD分层架构的演进
  • 5. 小结

在这里插入图片描述


引言

随着微服务架构的广泛应用,如何设计一个易于扩展、维护且具备高内聚、低耦合的系统架构成为了开发者和架构师们共同面临的挑战。DDD(领域驱动设计)为这一问题提供了有力的指导,尤其是DDD的分层架构,它通过层次化的设计有效降低了不同层之间的耦合度,提升了系统的灵活性和可演化性。

接下来,我们将详细讨论DDD分层架构的核心思想和设计模式,分析如何将它应用到微服务架构中,并通过具体示例来说明如何从传统三层架构演进到DDD分层架构。我们还会探讨DDD分层架构如何帮助微服务的架构演进,以便应对快速变化的业务需求。

1. 什么是DDD分层架构

领域驱动设计(Domain-Driven Design,DDD)是一种设计方法论,它强调通过对领域的深入理解,驱动软件的设计与架构。而DDD分层架构是DDD中一种经典的架构模式,它帮助开发者将复杂的业务逻辑分割成不同的层次,每个层次负责不同的职责。通过这种方式,DDD分层架构使得系统的业务逻辑更加清晰,架构的维护与演进也变得更加容易。


1.1 DDD分层架构的演变

DDD分层架构并非一成不变的,它经历了多个版本的演变。从最初的传统四层架构,到后来的五层架构,每次演变都在解决层间依赖、职责划分和架构灵活性的问题。我们先从传统的四层架构开始,逐步了解它是如何通过优化演变为DDD分层架构的。
在这里插入图片描述

在最早的传统四层架构中,基础层是被其它层依赖的,它位于最核心的位置,那按照分层架构的思想,它应该就是核心,但实际上领域层才是软件的核心,所以这种依赖是有问题的。后来我们采用了依赖倒置(Dependency inversionprinciple,DIP)的设计,优化了传统的四层架构,实现了各层对基础层的解耦

1.2 四层架构的起源与问题

最初的四层架构包括:

  1. 用户接口层:负责与外部交互,向用户展示信息。
  2. 应用层:处理业务流程和用例,协调领域层的操作。
  3. 领域层:包含领域模型和核心业务逻辑,是系统的核心。
  4. 基础层:提供数据库、消息中间件等底层服务。

传统的四层架构存在一个问题:基础层通常是其他层的依赖,导致架构不够灵活。随着业务的扩展,这种依赖关系会导致层与层之间的耦合度过高,系统变得难以维护和扩展。

1.3 依赖倒置和五层架构

为了优化四层架构的缺陷,DDD引入了依赖倒置(Dependency Inversion Principle,DIP)。通过这一原则,应用层和领域层可以独立于基础层进行设计和实现,从而实现各层之间的解耦

随着DDD分层架构的演进,五层架构(DCI架构)应运而生。在这一架构中,新增了上下文层(Context Layer),进一步清晰了各层之间的交互关系。


2. DDD分层架构的核心层次

DDD分层架构最常见的形式包括四个核心层次:用户接口层、应用层、领域层和基础层。每个层次都有其特定的职责,确保了系统的高内聚与低耦合。

在这里插入图片描述

2.1 用户接口层(User Interface Layer)

用户接口层的职责是与外部世界进行交互,获取用户的输入并展示系统的输出。这里的“用户”不仅仅指人类用户,还包括程序、自动化测试脚本、批处理任务等。

职责

  • 接收用户输入或请求。
  • 向用户展示结果。
  • 可以通过API暴露给外部系统,支持微服务之间的通信。

用户接口层的关键在于它不处理复杂的业务逻辑,而是负责业务逻辑的展示和用户交互的管理。所有的用户交互都通过用户接口层进行,从而保证了业务逻辑层与外部交互的分离。


2.2 应用层(Application Layer)

应用层是DDD分层架构中最薄的一层,它不直接包含业务逻辑,而是充当业务逻辑的协调者。应用层的主要职责是处理业务流程和用例,调用领域层来执行具体的业务逻辑。

职责

  • 定义应用的业务用例。
  • 协调多个聚合或领域对象的协作。
  • 调用领域层的服务,执行特定的业务操作。
  • 处理跨服务的调用,管理微服务之间的业务流。

应用层的设计非常重要,错误的设计会导致业务逻辑的“外泄”,使得应用层承担过多的职责。应用层不应包含领域模型的复杂业务逻辑,而应专注于用例的组合与协调。


2.3 领域层(Domain Layer)

领域层是DDD架构的核心层,负责实现系统的核心业务逻辑。领域层的设计基于领域模型,它由一系列领域对象构成,包含实体、值对象、聚合、领域服务等。领域层的关键在于充血模型,它强调将业务逻辑封装到实体和领域服务中,而不是将业务逻辑拆散到其他层次。

职责

  • 包含领域模型、业务规则和核心业务逻辑。
  • 定义聚合根、实体、值对象和领域服务。
  • 确保系统的业务逻辑与领域概念紧密关联。

领域层的设计应该尽可能反映真实世界的业务需求,领域服务负责在业务逻辑复杂时,协调多个聚合或领域对象来实现业务操作。


2.4 基础层(Infrastructure Layer)

基础层为系统提供通用的技术服务,如数据库访问、缓存、消息中间件等。基础层的设计采用依赖倒置原则,确保它不与领域层或应用层紧密耦合。

职责

  • 提供底层服务,如持久化、消息队列、缓存等。
  • 封装与外部系统的交互,如数据库、第三方API等。
  • 实现仓储模式(Repository),将数据访问的实现与业务逻辑解耦。

基础层的设计需要关注如何确保底层技术服务与业务层的独立性,以便后期可以方便地替换或优化底层实现。


3. DDD分层架构的重要原则

DDD分层架构遵循一系列的设计原则,确保系统的灵活性和可维护性。最重要的原则之一是“每层只能与其下方的层发生耦合”。这一原则的实施确保了不同层之间的责任清晰,降低了系统的复杂性。

3.1 严格分层架构 vs 松散分层架构

DDD分层架构可以分为两种:严格分层架构和松散分层架构。

  • 严格分层架构:每层只能依赖于其下方的直接层。例如,应用层只能调用领域层,领域层只能调用基础层。这样的设计确保了服务之间的依赖关系清晰,易于管理。

  • 松散分层架构:某些层可以与其下方的任意层产生依赖,依赖关系较为复杂,适用于更灵活的设计需求。

对于大多数项目而言,采用严格分层架构可以带来更高的可管理性和维护性。尤其是在微服务架构中,严格分层架构有助于保持服务的清晰边界,避免服务间的相互干扰。


3.2 依赖倒置原则(DIP)

依赖倒置是DDD架构中的核心设计原则。它要求高层模块(如应用层、领域层)不应依赖于低层模块(如基础层),而是通过接口或抽象层来进行解耦。通过这种方式,系统可以轻松应对底层技术的变化(如数据库切换、缓存服务更换等),而不需要大规模修改上层逻辑。


4. DDD分层架构的演进

随着业务的变化,领域模型和微服务架构也会经历演进。DDD分层架构为这一演进提供了很好的支持。通过对业务逻辑进行精细化的分层和模块化,我们可以灵活应对业务变化,确保架构的稳定性和扩展性。

4.1 领域模型与微服务架构的演进

领域模型不是一成不变的,随着业务需求的变化,领域模型也会经历不断的调整和重构。在DDD分层架构中,应用层负责协调各个微服务之间的业务操作,因此微服务的演进往往伴随着领域模型的调整。

微服务架构的演进

领域模型中对象的层次从内到外依次是:值对象、实体、聚合和限界上下文.

实体或值对象的简单变更,一般不会让领域模型和微服务发生大的变化。但聚合的重组或拆分却可以。这是因为聚合内业务功能内聚,能独立完成特定的业务逻辑。那聚合的重组或拆分,势必就会引起业务模块和系统功能的变化了。

这里我们可以以聚合为基础单元,完成领域模型和微服务架构的演进。聚合可以作为一个整体,在不同的领域模型之间重组或者拆分,或者直接将一个聚合独立为微服务
在这里插入图片描述

结合上图,以微服务 1 为例,讲解下微服务架构的演进过程:

  • 当发现微服务 1 中聚合 a 的功能经常被高频访问,以致拖累整个微服务 1 的性能时,我们可以把聚合 a 的代码,从微服务 1 中剥离出来,独立为微服务 2。这样微服务 2 就可轻松应对高性能场景。

  • 在业务发展到一定程度以后,你会发现微服务 2 的领域模型有了变化,聚合 d 会更适合放到微服务 1 的领域模型中。这时你就可以将聚合 d 的代码整体搬迁到微服务 1 中。如果你在设计时已经定义好了聚合之间的代码边界,这个过程不会太复杂,也不会花太多时间。

  • 最后我们发现,在经历模型和架构演进后,微服务 1 已经从最初包含聚合 a、b、c,演进为包含聚合 b、c、d 的新领域模型和微服务了。


微服务内服务的演进

微服务内部,实体的方法被领域服务组合和封装,领域服务又被应用服务组合和封装

在这里插入图片描述

在服务设计时,你并不一定能完整预测有哪些下层服务会被多少个上层服务组装,因此领域层通常只提供一些原子服务,比如领域服务 a、b、c。但随着系统功能增强和外部接入越来越多,应用服务会不断丰富。有一天你会发现领域服务 b 和 c 同时多次被多个应用服务调用了,执行顺序也基本一致。这时你可以考虑将 b 和 c 合并,再将应用服务中 b、c 的功能下沉到领域层,演进为新的领域服务(b+c)。这样既减少了服务的数量,也减轻了上层服务组合和编排的复杂度.


4.2 从三层架构到DDD分层架构的转型

传统的三层架构通常将业务逻辑和数据访问逻辑混合在一起,而DDD分层架构通过分离领域层、应用层和基础层,清晰地定义了各层的职责。这一转型过程通常需要以下几个步骤:

  1. 明确领域模型:首先需要深入理解业务需求,设计出符合业务场景的领域模型。
  2. 拆分业务逻辑:将复杂的业务逻辑拆分到领域层中,避免让应用层承担过多的业务处理。
  3. 重构基础层:基础层不应直接依赖于业务层,而是通过接口与领域层和应用层进行交互。

在这里插入图片描述
三层架构向 DDD 分层架构演进,主要发生在业务逻辑层和数据访问层.

  • DDD 分层架构在用户接口层引入了 DTO,给前端提供了更多的可使用数据和更高的展示灵活性。DDD 分层架构对三层架构的业务逻辑层进行了更清晰的划分,改善了三层架构核心业务逻辑混乱,代码改动相互影响大的情况。DDD 分层架构将业务逻辑层的服务拆分到了应用层和领域层。应用层快速响应前端的变化,领域层实现领域模型的能力

  • 另外一个重要的变化发生在数据访问层和基础层之间。三层架构数据访问采用 DAO 方式;DDD 分层架构的数据库等基础资源访问,采用了仓储(Repository)设计模式,通过依赖倒置实现各层对基础资源的解耦。仓储又分为两部分:仓储接口和仓储实现。仓储接口放在领域层中,仓储实现放在基础层。原来三层架构通用的第三方工具包、驱动、Common、Utility、Config 等通用的公共的资源类统一放到了基础层


5. 小结

DDD分层架构微服务架构的设计提供了强有力的支持。它通过将复杂的业务逻辑分层管理,使得系统更加模块化、灵活,并且能够随着业务需求的变化进行调整。在实际应用中,通过严格分层和依赖倒置,DDD架构能够有效降低各层之间的耦合,提高系统的可维护性和扩展性。

随着微服务架构和业务需求的不断变化,DDD分层架构也会不断演进,成为更加灵活、可扩展的解决方案。

在这里插入图片描述


http://www.ppmy.cn/ops/154777.html

相关文章

kafka消费者详细介绍(超级详细)

文章目录 一、Kafka 消费者与消费者组1.1 Kafka 消费者(Consumer)概述1.1.1 消费者工作流程1.1.2 消费者的关键配置 1.2 Kafka 消费者组(Consumer Group)概述1.2.1 消费者组的工作原理1.2.2 消费者组的优点1.2.3 消费者组的再均衡…

Linux网络编程中的零拷贝:提升性能的秘密武器

在当今数字化时代,网络应用的性能至关重要。而在网络编程中,数据传输的效率直接影响着应用的整体性能。传统的数据传输方式往往涉及大量的数据拷贝和上下文切换,这在高并发、大数据量的场景下,会成为性能瓶颈。零拷贝技术的出现&a…

25.Word:学生成绩管理系统【8】

目录 NO1.2​ NO3 NO4.5.6 NO7.8.9​​ NO1.2 F12另存为→考生文件夹布局→页面设置对话框→纸张大小→页边距:上下左右→文档网格: NO3 布局→分隔符→分节符:下一页(封面、目录、一、二、三、四)6节双击页眉页…

Kotlin开发(六):Kotlin 数据类,密封类与枚举类

引言 想象一下,你是个 Kotlin 开发者,敲着代码忽然发现业务代码中需要一堆冗长的 POJO 类来传递数据。烦得很?别急,Kotlin 贴心的 数据类 能帮你自动生成 equals、hashCode,直接省时省力!再想想需要多种状…

React第二十八章(css modules)

css modules 什么是 css modules 因为 React 没有Vue的Scoped,但是React又是SPA(单页面应用),所以需要一种方式来解决css的样式冲突问题,也就是把每个组件的样式做成单独的作用域,实现样式隔离,而css modules就是一种…

directx12 3d+vs2022游戏开发第一章 笔记三 向量代数

一、向量类型 1.局部变量或全局变量用XMVECTOR 类型。 2. 对于类中的数据成员, 使用XMFLOAT2(2d向量)、XMFLOAT3(3d向量)和XMFLOAT4(4d向量) 类型。 3. 在运算之前, 通过加载函数将XMFLOATn类型转换为 XMV…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.18 逻辑运算引擎:数组条件判断的智能法则

1.18 逻辑运算引擎:数组条件判断的智能法则 1.18.1 目录 #mermaid-svg-QAFjJvNdJ5P4IVbV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QAFjJvNdJ5P4IVbV .error-icon{fill:#552222;}#mermaid-svg-QAF…

蓝桥杯3518 三国游戏 | 排序

题目传送门 这题的思路很巧妙,需要算出每个事件给三国带来的净贡献(即本国士兵量减其他两国士兵量)并对其排序,根据贪心的原理累加贡献量直到累加结果不大于0。最后对三国的胜利的最大事件数排序取最值即可。 n int(input()) a …