DDD - 领域驱动设计分层架构:构建可演化的微服务架构
文章目录
- 引言
- 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分层架构的演进
- 4.1 领域模型与微服务架构的演进
- 微服务架构的演进
- 微服务内服务的演进
- 4.2 从三层架构到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.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分层架构通过分离领域层、应用层和基础层,清晰地定义了各层的职责。这一转型过程通常需要以下几个步骤:
- 明确领域模型:首先需要深入理解业务需求,设计出符合业务场景的领域模型。
- 拆分业务逻辑:将复杂的业务逻辑拆分到领域层中,避免让应用层承担过多的业务处理。
- 重构基础层:基础层不应直接依赖于业务层,而是通过接口与领域层和应用层进行交互。
三层架构向 DDD 分层架构演进,主要发生在业务逻辑层和数据访问层.
-
DDD 分层架构在用户接口层引入了 DTO,给前端提供了更多的可使用数据和更高的展示灵活性。DDD 分层架构对三层架构的业务逻辑层进行了更清晰的划分,改善了三层架构核心业务逻辑混乱,代码改动相互影响大的情况。DDD 分层架构将业务逻辑层的服务拆分到了应用层和领域层。应用层快速响应前端的变化,领域层实现领域模型的能力
-
另外一个重要的变化发生在数据访问层和基础层之间。三层架构数据访问采用 DAO 方式;DDD 分层架构的数据库等基础资源访问,采用了仓储(Repository)设计模式,通过依赖倒置实现各层对基础资源的解耦。仓储又分为两部分:仓储接口和仓储实现。仓储接口放在领域层中,仓储实现放在基础层。原来三层架构通用的第三方工具包、驱动、Common、Utility、Config 等通用的公共的资源类统一放到了基础层
5. 小结
DDD分层架构为微服务架构的设计提供了强有力的支持。它通过将复杂的业务逻辑分层管理,使得系统更加模块化、灵活,并且能够随着业务需求的变化进行调整。在实际应用中,通过严格分层和依赖倒置,DDD架构能够有效降低各层之间的耦合,提高系统的可维护性和扩展性。
随着微服务架构和业务需求的不断变化,DDD分层架构也会不断演进,成为更加灵活、可扩展的解决方案。
相关文章:

DDD - 领域驱动设计分层架构:构建可演化的微服务架构
文章目录 引言1. 什么是DDD分层架构?1.1 DDD分层架构的演变1.2 四层架构的起源与问题1.3 依赖倒置和五层架构 2. DDD分层架构的核心层次2.1 用户接口层(User Interface Layer)2.2 应用层(Application Layer)2.3 领域层…...

2025数学建模美赛|赛题翻译|E题
2025数学建模美赛,E题赛题翻译 更多美赛内容持续更新中......

DeepSeek-V3 与 DeepSeek R1 对比分析:技术与应用的全面解析
一、背景 在当今科技飞速发展的时代,深度学习技术如同一股强大的浪潮,席卷了自然语言处理(NLP)、计算机视觉(CV)以及多模态模型等众多领域。从智能语音助手到图像识别技术,从文本生成工具到多模…...

qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记
qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记 文章目录 qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记1.例程运行效果2.例程缩略图3.项目文件列表4.main.qml5.main.cpp6.CMakeLists.txt 1.例程运行效果 运行该项目需要自己准备一个模型文件 2.例程缩略图…...
Linux内核中的页面错误处理机制与按需分页技术
在现代操作系统中,内存管理是核心功能之一,而页面错误(Page Fault)处理机制是内存管理的重要组成部分。当程序访问一个尚未映射到物理内存的虚拟地址时,CPU会触发页面错误异常,内核需要捕获并处理这种异常,以决定如何响应,例如加载缺失的页面、处理权限错误等。Linux内…...

PHP实现混合加密方式,提高加密的安全性(代码解密)
代码1: <?php // 需要加密的内容 $plaintext 授权服务器拒绝连接;// 1. AES加密部分 $aesKey openssl_random_pseudo_bytes(32); // 生成256位AES密钥 $iv openssl_random_pseudo_bytes(16); // 生成128位IV// AES加密(CBC模式)…...

使用openwrt搭建ipsec隧道
背景:最近同事遇到了个ipsec问题,做的ipsec特性,ftp下载ipv6性能只有100kb, 正面定位该问题也蛮久了,项目没有用openwrt, 不过用了开源组件strongswan, 加密算法这些也是内核自带的,想着开源的不太可能有问题ÿ…...
大语言模型(LLM)模拟金融市场参与者行为
大语言模型(LLM)模拟金融市场参与者行为 研究背景 传统深度学习模型通过识别市场数据历史模式预测市场,但未捕捉个体决策过程。LLM 虽能学习人类对不同提示的反应,但在模拟金融市场参与者时面临挑战:个体投资者不总是理性决策,LLM 可能无法捕捉;LLM 数值和金融知识可靠…...
用一个例子详细说明python单例模式
单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。这在需要控制资源(如数据库连接、文件系统等)的访问时非常有用。 下面是一个使用Python实现单例模式的例子: class Singleton:…...

第1章 量子暗网中的血色黎明
月球暗面的危机与阴谋 量子隧穿效应催生的幽蓝电弧,于环形山表面肆意跳跃,仿若无数奋力挣扎的机械蠕虫,将月球暗面的死寂打破,徒增几分诡异。艾丽伫立在被遗弃的“广寒宫”量子基站顶端,机械义眼之中,倒映着…...
LeetCode--84. 柱状图中最大的矩形【单调栈】
84. 柱状图中最大的矩形 正文 题目如下 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 这道题暴力很简单,但是时间复杂度是O(N^2)…...

网络工程师 (8)存储管理
一、页式存储基本原理 (一)内存划分 页式存储首先将内存物理空间划分成大小相等的存储块,这些块通常被称为“页帧”或“物理页”。每个页帧的大小是固定的,例如常见的页帧大小有4KB、8KB等,这个大小由操作系统决定。同…...
【Leetcode 每日一题】541. 反转字符串 II
问题背景 给定一个字符串 s s s 和一个整数 k k k,从字符串开头算起,每计数至 2 k 2k 2k 个字符,就反转这 2 k 2k 2k 字符中的前 k k k 个字符。 如果剩余字符少于 k k k 个,则将剩余字符全部反转。如果剩余字符小于 2 k…...

MSA Transformer
过去的蛋白质语言模型以单个序列为输入,MSA Transformer以多序列比对的形式将一组序列作为输入。该模型将行和列注意力交织在输入序列中,并在许多蛋白质家族中使用mask语言建模目标进行训练。模型的性能远超过了当时最先进的无监督学习方法,其…...
Vue.js组件开发-实现全屏焦点图片带图标导航按钮控制图片滑动切换
使用 Vue 实现全屏焦点图片带图标导航按钮控制图片滑动切换 步骤 创建 Vue 项目:可以使用 Vue CLI 快速创建一个新的 Vue 项目。设计组件结构:创建一个包含图片展示区域和导航按钮的组件。实现图片滑动切换逻辑:通过点击导航按钮切换图片。…...

Linux系统上安装与配置 MySQL( CentOS 7 )
目录 1. 下载并安装 MySQL 官方 Yum Repository 2. 启动 MySQL 并查看运行状态 3. 找到 root 用户的初始密码 4. 修改 root 用户密码 5. 设置允许远程登录 6. 在云服务器配置 MySQL 端口 7. 关闭防火墙 8. 解决密码错误的问题 前言 在 Linux 服务器上安装并配置 MySQL …...
Vue 3 30天精进之旅:Day 10 - Vue Router
在现代单页面应用(SPA)中,路由管理是必不可少的一部分。Vue Router是Vue.js官方的路由管理库,它使得在Vue应用中实现路由变得简单而灵活。今天的学习将围绕以下几个方面展开: Vue Router概述安装和基本配置定义路由路…...

人工智能如何驱动SEO关键词优化策略的转型与效果提升
内容概要 随着数字化时代的到来,人工智能(AI)技术对各行各业的影响日益显著,在搜索引擎优化(SEO)领域尤为如此。AI的应用不仅改变了关键词研究的方法,而且提升了内容生成和搜索优化的效率&…...

keil5如何添加.h 和.c文件,以及如何添加文件夹
1.简介 在hal库的编程中我们一般会生成如下的几个文件夹,在这几个文件夹内存储着各种外设所需要的函数接口.h文件,和实现函数具体功能的.c文件,但是有时我们想要创建自己的文件夹并在这些文件夹下面创造.h .c文件来实现某些功能,…...
BMC PSL function(22)-printf()
printf() 含义:Print text formatted to the C library printf() routine specification Format printf(format,[arg1,......,argn]) Parameter ParameterDefinitionformattext, variable names, and control characters that specify the content and format of output t…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...