导图社区 领域驱动设计DDD
领域驱动设计(DDD)实战指南:从模型到架构的思维跃迁 DDD通过领域模型和通用语言破解复杂业务难题核心要素包括六边形架构的分层策略(端口与适配器)、聚合根与值对象的精准设计,以及限界上下文的边界划分领域模型分为四类(充血/贫血/失血/胀血),需警惕过时模式业务对象模型串联实体、事件与服务,而分层架构(四/五/六层)需匹配业务复杂度关键原则:以领域为核心,用适配器隔离技术细节,让架构随业务进化。
编辑于2026-02-27 21:31:55在AI技术飞速发展的当下,AI动画生成成为了创意领域的新宠,为创作者们打开了全新的创作大门。这张由EdrawMind精心构建的AI动画生成思维导图模板,宛如一位贴心的创作指南,为想要涉足或深耕AI动画生成领域的人士提供了清晰且全面的流程指引。在故事脚本环节,不仅介绍了以人类灵感为起点借助LLM大语言模型发散的创作方式,还列举了如DeepSeek、ChatGPT、豆包等实用的工具,为创作者的故事构思提供了丰富的灵感源泉和高效的操作途径。AI创作全流程指南:从脚本到成片的一站式解决方案,"用AI将灵感一键变成影片!" 覆盖动画生成、字幕添加、视频修复、剪辑配乐全流程新手推荐剪映 Topaz Video组合,快速上手画质提升进阶可选Runway等闭源工具获得更高品质关键技巧:分镜脚本决定影片骨架,Prompt优化影响生成质量,商用需注意版权一致性控制是难点,推荐分步生成角色与场景AI配音可选商用平台或自训练模型,字幕剪辑用剪映最便捷。对于适用人群,无论是充满创意的动画爱好者,渴望用AI技术将自己的奇思妙想变成生动的动画作品,此模板都能发挥巨大价值。
【改变人生的101部必看电影】这份片单带你探索生命意义、亲情友情、职场觉醒等7大主题从《超脱》的哲学思考到《教父》的人性剖析,从《星际穿越》的宏大命题到《我是山姆》的温情治愈,每部电影都是人生的缩影《盗梦空间》烧脑反转,《断背山》细腻动人,《素媛》发人深省,《白日梦想家》激励追梦无论你想寻找自我、治愈心灵还是思考世界,总有一部能触动你。
穿越荆棘与偏见,简·爱以瘦弱身躯呐喊出灵魂平等的强音。这不仅是爱情的颂歌,更是独立人格的觉醒。翻开它,让那份不屈的尊严点燃你内心的火焰!
社区模板帮助中心,点此进入>>
在AI技术飞速发展的当下,AI动画生成成为了创意领域的新宠,为创作者们打开了全新的创作大门。这张由EdrawMind精心构建的AI动画生成思维导图模板,宛如一位贴心的创作指南,为想要涉足或深耕AI动画生成领域的人士提供了清晰且全面的流程指引。在故事脚本环节,不仅介绍了以人类灵感为起点借助LLM大语言模型发散的创作方式,还列举了如DeepSeek、ChatGPT、豆包等实用的工具,为创作者的故事构思提供了丰富的灵感源泉和高效的操作途径。AI创作全流程指南:从脚本到成片的一站式解决方案,"用AI将灵感一键变成影片!" 覆盖动画生成、字幕添加、视频修复、剪辑配乐全流程新手推荐剪映 Topaz Video组合,快速上手画质提升进阶可选Runway等闭源工具获得更高品质关键技巧:分镜脚本决定影片骨架,Prompt优化影响生成质量,商用需注意版权一致性控制是难点,推荐分步生成角色与场景AI配音可选商用平台或自训练模型,字幕剪辑用剪映最便捷。对于适用人群,无论是充满创意的动画爱好者,渴望用AI技术将自己的奇思妙想变成生动的动画作品,此模板都能发挥巨大价值。
【改变人生的101部必看电影】这份片单带你探索生命意义、亲情友情、职场觉醒等7大主题从《超脱》的哲学思考到《教父》的人性剖析,从《星际穿越》的宏大命题到《我是山姆》的温情治愈,每部电影都是人生的缩影《盗梦空间》烧脑反转,《断背山》细腻动人,《素媛》发人深省,《白日梦想家》激励追梦无论你想寻找自我、治愈心灵还是思考世界,总有一部能触动你。
穿越荆棘与偏见,简·爱以瘦弱身躯呐喊出灵魂平等的强音。这不仅是爱情的颂歌,更是独立人格的觉醒。翻开它,让那份不屈的尊严点燃你内心的火焰!
领域驱动设计 DDD
概念
领域
核心思想
通过领域驱动设计方法定义领域模型,从而确定 业务和应用边界,保证业务模型与代码模型的一致性
子域
核心子域
当前领域的最核心的竞争力,也就是业务核心
如何明确核心域呢——精炼业务域
领域愿景说明
突出核心
精炼文档
标明核心
内聚机制
通用子域
支撑子域
通用语言
限界上下文
限界
领域的边界,也就是范围
上下文
语义环境
实体
实体核心是用唯一的标识符来定义,而不是通过属性来定义
即使属性完全相同也可能是两个不同的对象
实体本身是有状态的
实体有演进的生命周期
实体本身会体现出相关的业务行为,业务行为会对实体属性或状态造成影响和改变
值对象
用于描述领域的某个方面本身没有概念标识的对象,值对象被实例化后只是提供值或叫设计元素,我们只关心这些设计元素是什么?而不关心这些设计元素是谁
无状态,不产生行为,不存在生命周期演进
两种形态
单一属性
比如你的值对象可能是一个Address,而这个地址可能就是一个json形态的数据集, 那么这个时候你直接把你的值对象直接当成一个实体类当中的其中一个属性就OK了
多个属性
可以考虑把我们的值对象做为单独的一个实体类Class。 而实体想要使用我们的值对象,直接对值对象进行引用即可
聚合和聚合根
聚合
将实体和值对象划分为聚合并围绕着聚合定义边界。选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制
聚合是业务和逻辑紧密关联的实体和值对象组合而成
聚合是数据修改和持久化的基本单元,一个聚合对应一个数据的持久化
将下单操作与支付操作做为一个整体。这个叫做聚合。像这种业务 一体化的操作或者这种可以当作原子性聚合的操作,都可以称之为聚合
聚合根
订单中有用户id,订单中也有支付单号,也有商品编号等等。那么相当于我们的订单对象就是这个聚合的关联者,同时也是管理者。那么我们的订单对象就是我们整个模块的聚合根
聚合根是实体,拥有实体的业务属性和行为,同时也是聚合的管理者, 负责协调聚合内的实体和值对象,按照固定的业务规则,完成业务逻辑
聚合根是聚合对外唯一的接口人,聚合之间以聚合根ID关联的方式接受聚合的外部任务和请求,聚合外不能通过对象引用的方式访问聚合内的对象。需要将关联的聚合根ID作为入参,先访问聚合根,再通过聚合根导航到聚合内部实体
如果聚合根被删除了,他引用的实体和值对象就不会存在了
聚合根和聚合根所在层的领域服务都可以组合多个实体完成领域逻辑,但为了DDD分层架构的职责单一,聚合根最好只承担聚合管理职能,只实现聚合内实体和聚合根本身相关的业务逻辑,而跨多个实体的复杂领域逻辑统一放到领域服务中实现
领域建模中,可能存在一些独立的找不到聚合根的实体, 但可以根据高度依赖的业务逻辑,把这些实体集合也作为聚合处理
聚合对外的操作入口就是我们的聚合根,聚合内的所有操作都必须由聚合根来进行
聚合边界划分指导原则
生命周期一致性原则
生命周期一致性是指聚合内部的对象,应该和聚合根具有相同的 生命周期,聚合根消失,则聚合内部的所有对象都应该一起消失
比如支付没有单独存在的意义,那么支付比下单操作生命周期长又有什么意义呢? 如果这个支付还能支持其他的模块,比如你的电商还有会员售卖,那么你就应该 把支付进行设计,而不是属于这个聚合
问题域一致性原则
不属于同一个问题域的对象,不应该出现在同一个聚合中
比如我们的电商网站上,订单与支付存在聚合,而订单显然就是我们的聚合根,那么订单被删除,我们的支付也要消失,那么支付一定属于订单聚合吗
我们来思考下,比如我们有会员系统,会员系统需要购买才能够提升会员等级,那么显然我们的会员系统也能够跟支付产生聚合。而这个时候如果只会由于订单与原本的支付存在逻辑关联就让订单聚合,显然约束了我们的支付的适用度以及作用域
场景一致性原则
经常被同时操作的对象,应该属于同一个聚合,而那些极少 被同时关注的对象,即使上面两个原则都满足也不应该划为一个聚合
在很多业务场景中,我们会对领域对象进行查看、修改等各种操作。不在同一个场景下操作的对象,放入同一个聚合意味着每次操作一个对象,就需要把其他对象的所有信息抓取到,这是非常没有意义的。从实现层次,如果不紧密相关的对象出现在同一个聚合中,会导致它们经常在不同的场景中被并发修改,也增加了这些对象之间冲突的可能性
所以大多数时候的操作场景都不一致的对象,应该把它们分到不同的聚合中
聚合应尽可能地小
通常,较小的聚合会让一个系统变得更快和更可靠, 因为会传输较小的数据并且引发并发冲突的概率会较小
设计一个大的聚合会带来各种问题:
大聚合会降低性能
聚合中的每个成员会增加数据的量,当这些数据需要从数据库中 进行加载的时候,大聚合会增加额外的查询,导致性能降低
大聚合更容易受到并发冲突的影响
大聚合可能包含了很多职责,这意味着它要参与多个业务用例。 随之而来的就是,有很大可能出现多个用户对单个聚合进行变更的情况, 从而导致了严重的并发冲突,影响了程序的可用性和用户体验
大聚合扩展性差
大聚合意味着与更多的模型产生依赖关系,这会导致重构和扩展的难度增加
领域服务
领域服务是很薄的一层
有些重要的领域操作,不适合归到实体(Entity)和值对象(value object)的类别中,这些操作从本质上讲是有些活动或动作,而不是事物,当领域中的某个重要过程或转换操作不属于实体或值对象的自然职责时,应该在模型中添加一个作为独立接口的操作,并将其中命为Service
在领域层,实体干不了的(或者说不属于实体的)操作,就交给领域服务
领域服务是实体的一种补充,是一种必要的妥协
什么样的操作该放入领域服务中
涉及到跨越多个实体的操作
比如内部转账,从一个账户实体到另一个账户实体
涉及到和外部系统的交互
还是举个转账的场景,在转账的时候,需要调用实体 的转账方法,然后再调用第三方网关(支付宝/微信)
这种时候由于转账是核心业务,不适合放到应用服务层,但是由于要调 第三方网关,也不适合放入实体,这时候就应该把这个逻辑写到领域服务中
约束
不能在领域服务里写太多的业务逻辑
不能在领域服务里调用dao和仓储
领域服务视为实体的一种补充,里面的属性和逻辑也和 实体一样不能是基础类型,得是含有业务含义的值对象
领域服务之间可以进行调用,最好是保持父域的领域 服务调用子域的领域服务,不允许跨越上下文进行调用
和实体一样,如果有不相关的领域服务的调用, 或者有跨上下文的情况,使用领域事件进行解耦
QA
必须要通过领域服务才能操作到实体吗?
并非,领域服务只是实体逻辑的一点补充,如果可以直接在 应用层调用实体的方法完成业务,那就不需要调领域服务
可以在领域服务内调用dao层吗?领域服务可以调仓储吗?
理论上是可以的,但是不推荐这么干,我们得尽量保证领域服务 是很薄的一层,不额外的去增加领域层的依赖,让领域层变的好验证
虽然说可以通过接口mock或者是stub的方式进行模拟测试,但依然需要开发成本
如果规定调用实体必须得通过领域服务,那么可以在领域服务调用仓储和dao
如果规定可以直接在应用层调用实体的方法,那么就不能在领域服务内调用仓储和dao
领域事件
领域模型
领域模型是对领域内的概念类或现实世界中对象的可视化表示
领域模型在业务中有一个名字,叫做业务对象模型
业务对象模型是用来描述业务对象之间的引用关系
业务角色
业务角色表示的是一个角色承担的一系列责任
比如收银员,他的责任是计算商品价格,收钱,找零,甚至退换货
业务实体
业务实体表示的是你实际上使用或者可交付的工件,资源,事件
比如电商项目中的商品,你需要给买家打印的发票
业务用例
业务用例显示的是协作角色与业务实体之间 如何执行工作流程,也就是我们的业务链路
领域模型分类
失血模型
失血模型实际上就是我们的对象模型中只包含我们的get,set方法
像我们的排序,分页等等任何的通用性操作都不会包含在我们的对象中
失血模型是没有Dao层的,我们所有的业务会全部写在我们的Service当中
一般情况下,我们是不推荐用这种模型的
优点
领域对象结构简单
缺点
肿胀的业务服务代码逻辑,难于理解和维护
无法良好的应对复杂业务逻辑和场景
贫血模型
贫血模型实际上就是在失血模型的基础上增加了不依赖于持久化的原子领域逻辑
比如我们经常会使用到的排序,分页等等操作,都可以定义在我们的这个对象当中
而任何跟持久化相关的操作,你都需要在业务逻辑层实现
这种也是现在大家最常用的一种建模方式
优点
层次结构清楚,各层之间单向依赖
对于只有少量业务逻辑的应用来说,使用起来非常自然
开发迅速,易于理解
缺点
无法良好的应对非常复杂逻辑和场景
充血模型
充血模型中实际上我们的领域对象不仅仅包含了 我们的非持久化逻辑,甚至还包含了我们的持久化逻辑
业务层实际上只会做一些整合的操作以及 封装事务,其他的操作都会在我们的领域对象中完成
优点
更加符合OO原则
业务逻辑层只充当事务管理以及整合的角色,不和DAO打交道,职责单一
缺点
持久化的内容都放在我们的领域对象里,所以我们在写业务的时候会深入 到领域对象去,这对于开发者的水平要求很高,变相的增加了企业的成本
领域对象包含了太多的操作,实例化时拿到了很多不需要的关联模型
胀血模型
胀血模型取消了Service层,只剩下domain object和DAO两层
所有的业务逻辑整合放在了领域对象里面,简单粗暴
事务,授权等等操作直接放在方法上或者对象上
优点
简化了代码分层结构
也算符合面向对象设计
缺点
代码理解和维护性差
在Domain Object的Domain Logic上面封装事务,授权等很多本不应该属于领域 对象的逻辑,使业务逻辑再次进行到混论的状态,引起了Domain Object模型的不稳定
领域模型对比使用
失血模型以及胀血模型已经不再被推荐使用
充血模型对于程序员要求极高,很多的项目都不会去这样设计
贫血模型是我们用得最多的
架构
四层架构
自上而下依次为
User Interface(用户界面/展现层)
负责向用户展现信息以及解释 用户命令,更细的方面来讲就是:
请求应用层以获取用户所需要展现的数据
发送命令给应用层要求其执行某个用户命令
Application(应用层)
很薄的一层,定义软件要完成的所有任务
对外为展现层提供各种应用功能(包括查询或命令)
对内调用领域层(领域对象或领域服务)完成各种业务逻辑
应用层不包含业务逻辑
Domain(领域层)
负责表达业务概念,业务状态信息以及业务规则
领域模型处于这一层,是业务软件的核心
Infrastructure(基础设施层)
为其他层提供通用的技术能力
提供了层间的通信
为领域层实现持久化机制
可以通过架构和框架来支持其他层的技术需求
补充说明
分层架构可以简单分为两种
严格分层架构
某层只能与位于其直接下方的层发生耦合
松散分层架构
允许某层与它的任意下方层发生耦合
传统的四层架构都是限定型松散分层架构
基础设施层的任意上层都可以访问该层(“L”型),而其它层遵守严格分层架构
并且上层架构可以调用下层架构,而下层架构则不能向上进行调用
五层架构
自上而下依次为
User Interface(用户接口层)
主要用于处理用户发送的Restful请求和解析用户 输入的配置文件等,并将信息传递给Application层的接口
Application(应用层)
负责多进程管理及调度、多线程管理及调度、多协程调度和维护业务实例的状态模型。当应用层收到用户接口层的请求后,委托Context层与本次业务相关的上下文进行处理
Context(环境层)
以上下文为单位,将Domain层的领域对象 cast成合适的role,让role交互起来完成业务逻辑
Domain(领域层)
定义领域模型,不仅包括领域对象及其之间 关系的建模,还包括对象的角色role的显式建模
Infrastructure(基础设施层)
为其他层提供通用的技术能力:业务平台,编程框架, 持久化机制,消息机制,第三方库的封装,通用算法等等
六层架构
自上而下依次为
User Interface(用户接口层)
主要用于处理用户发送的Restful请求和解析用户输入的 配置文件等,并将信息传递给Scheduler层的接口
Scheduler(调度层)
负责多进程管理及调度、多线程管理及调度、多协程调度和维护业务实例的状态模型。当调度层收到用户接口层的请求后,委托Transaction层与本次操作相关的事务进行处理
Transaction(事务层)
对应一个业务流程,比如UE Attach,将多个 同步消息或异步消息的处理序列组合成一个事务
在大多场景下,都有选择结构。万一事务执行失败,则立即进行回滚
当事务层收到调度层的请求后,委托Context层的Action进行处理, 常常还伴随使用Context层的Specification(谓词)进行Action的选择
Context(环境层)
以Action为单位,处理一条同步消息或异步消息
将Domain层的领域对象cast成合适的role,让role交互起来完成业务逻辑
环境层通常也包括Specification的实现,即通过Domain层的知识去完成一个条件判断
Domain(领域层)
定义领域模型,不仅包括领域对象及其之间 关系的建模,还包括对象的角色role的显式建模
Infrastructure(基础设施层)
为其他层提供通用的技术能力:业务平台,编程框架, 持久化机制,消息机制,第三方库的封装,通用算法等等
六边形架构
该架构是由端口及适配器组成。所以,这个架构也叫做端口和适配器架构
所谓的端口,实际上很多开发者会以接口组的形式去进行设计。 因为单纯的接口维度太小。而这无非就是我们的应用的出入口
适配器分类
主适配器
主要负责用户的访问,也就是从接收用户输入,调用用户端口并返回
次适配器
主要实现应用的出口端口,向外部工具执行操作。也就是你的ES,Mysql, Redis,又或者你的Email工具等等这些,都算是第三方的交互,统称为应用出口
这些适配器可以分布在六边形的每个侧边上,每个侧边都相当于一个类型的端口,端口要么处理输入,要么处理输出。对于外界的每一种类型,都会有专门的一个适配器与之对应以及匹配