DDD之我见:(一)概念介绍
领域驱动设计(Domain Driven Design)实际不是一个新的概念,2003年Eric Evans就出版了《领域驱动设计》一书。只是随着微服务、云原生等概念的兴起,大家发现DDD与微服务架构非常契合,慢慢的DDD就又走进了大家的视野,很多企业对DDD进行实践,把DDD作为拆分服务的重要方法论。
本文作为DDD系列的第一篇,首先对DDD中的相关概念做一个介绍,让初学者对DDD有一个初步的认识。
DDD看起来有很多名称和概念,但其实脱离不了面向对象设计的相关理念,DDD也只是在软件工程发展历程中总结和归纳出了一套实践方法,并为其取了一些看起来高大上的名称。(说这话只是想告诉初学者不要对DDD有畏惧心理,DDD实际不难。)
网络上大多数对DDD的讲解只停留在设计层面,而本系列文章想从一个开发者的角度,按如下从低到高的顺序介绍领域驱动设计:1、DDD是什么。2、DDD相关代码该如何搭建。3、如果领导分配了一个小的领域模块给我,我该如何进行战术设计。4、最后我如果是架构师,我该如何进行DDD的战略设计。
一、什么是DDD
软件系统随着业务的快速变化会变得越来越复杂,而为了应对越复杂的软件系统,我们的软件设计也要适应其发展,领域驱动设计(Domain Driven Design)的建立就是为了解决快速变化的复杂系统。
名称:Domain Driven Design 领域驱动设计
目的:将业务划分为边界清晰的模块
核心方法论:领域驱动模型,模型驱动软件设计。
1.1、为什么要用DDD
之所以有些项目会用到DDD,当然是因为其能解决项目中存在的一些问题。
比如说一个传统的MVC模式项目,一个Service类定义后被很多个其它服务所调用,那么当业务变动需要对这个Service进行重构,可能就需要耗费巨大的代价。而DDD是希望将“复用”这个概念提升到领域层面,不再局限于代码片段的简单复用,而是致力于构件可复用的业务逻辑模块,一次作为抵御业务需求频繁变动的坚实壁垒。
达到如下效果:
- 边界明确性:用限界上下文解决微服务 “拆什么、怎么拆” 的难题。
- 业务一致性:确保技术架构始终围绕核心业务逻辑构建,避免过度技术化导致的架构腐化。
- 演进可持续性:支持微服务架构随业务发展逐步迭代,而非一次性激进重构。
1.2、DDD的技术手段
为了实现更加优雅的业务变化应对,DDD 采用了领域建模、分层架构、事件驱动等多种设计模式和技术手段。
- 通过领域建模精准捕捉业务本质,构建出贴近业务实际的领域模型;
- 分层架构将系统划分为不同职责的层次,明确各层之间的交互边界,避免层与层之间的过度耦合;
- 事件驱动机制则通过发布 - 订阅模式实现业务模块之间的解耦,当某个业务事件发生时,相关模块能够自动响应处理,无需紧密依赖调用关系。
这些设计方法相互配合,让系统在面对业务变化时能够以更加灵活、高效的方式进行调整和扩展,真正实现 “以不变应万变”,让业务逻辑的复用价值得到最大化发挥。
二、DDD相关概念介绍
2.1、战略层相关概念
战略设计聚焦于领域的整体架构规划,解决 “做什么” 的问题
- 领域(Domain):一个特定的业务范围,包含一系列相关的业务活动和规则。
- 子领域(Subdomain): 领域的细分,可以分为核心子域、支撑子域、通用子域
- 核心子域:决定业务核心竞争力的部分(如电商中的订单系统)。
- 支撑子领域:支持核心业务的功能(如用户管理系统)。
- 通用子领域:可复用的公共功能(如身份认证)。
- 限界上下文:一个概念上的边界,其中每个领域模型元素(如术语、规则)具有明确的含义。
2.2、战术层相关概念
战术设计关注领域模型的具体实现,解决 “如何做” 的问题
- 领域模型(Domain Model):对领域内业务对象及其关系的抽象表示,反映业务本质规则。
- 实体(Entity):具有唯一标识符(ID),且状态会随时间变化的领域对象。
- 值对象(Value Object):无唯一标识符,仅通过属性值定义的对象,具有不可变性。
- 聚合(Aggregate):一组相关联的实体和值对象的集合,作为数据修改的最小单元。
- 聚合根(Aggregate Root):聚合的唯一入口,负责维护聚合内对象的生命周期和业务规则。
- 领域服务(Domain Service):实现领域内跨实体的业务逻辑,不属于任何特定实体或值对象。
- 领域事件(Domain Event):表示领域中发生的重要事件,用于跨聚合或上下文通信。(不可变、时间顺序)
- 仓储(Repository):封装数据持久化逻辑,为领域模型提供类似集合的接口。
- 工厂(Factory):创建复杂领域对象或聚合的封装机制,隐藏对象创建细节。
2.3、其它扩展概念
- 防腐层(Anticorruption Layer):就是把可能变化的服务抽离出来,其隔离不同上下文的模型差异。可以通过适配器模式进行数据转换。
- 事件风暴(Event Storming):通过协作研讨会识别领域事件和业务流程,构建领域模型。
- 四色建模法:用不同颜色标记领域对象类型(实体、命令、查询、事件),辅助模型设计。
三、与MVC模式对比
- 设计理念不同
- MVC主要目的是将数据处理和界面展示解耦,方便UI的修改和复用,本质上更偏向于用户界面层的架构
- DDD以业务领域为核心,强调业务领域的深入理解和建模,致力于将业务逻辑从技术实现中剥离出来,通过构件领域模型来准确反映业务本质,追求业务逻辑的高内聚、低耦合与可复用性。
- 架构分层不同
- MVC 模式的分层较为简单直接,主要分为视图层、控制层和模型层。
- DDD 的架构分层更为复杂和精细,通常包含用户界面层、应用层、领域层和基础设施层。
- 耦合度
- MVC耦合度较高
- DDD高内聚低耦合,将业务逻辑高度内聚到领域层。防腐层也进一步降低了系统与外部服务之间的耦合。
DDD 的优缺点
- 优点:
- 业务驱动设计:以领域模型为核心,确保软件与业务需求高度对齐,适合复杂业务场景(如金融、供应链)。
- 复杂性管理:通过战略设计(子领域、限界上下文)拆分问题,战术设计(聚合、实体)封装领域逻辑,避免模型混乱。
- 长期可维护性:领域模型独立于技术实现,业务变化时只需调整模型,减少系统重构成本。
- 团队协作优化:通过 “通用语言” 促进领域专家与开发人员沟通,减少需求理解偏差。
- 缺点:
- 学习曲线陡峭:需要理解聚合、领域事件等复杂概念,对团队建模能力要求高。
- 实现成本高:初期需要投入大量时间进行领域分析与建模,不适合快速迭代的简单项目。
- 过度设计风险:中小型项目使用 DDD 可能导致架构臃肿(如强行划分聚合、仓储),反而降低开发效率。
- 分布式复杂度:与微服务结合时,跨上下文通信(如事件总线)增加系统调试难度。
MVC 的优缺点
- 优点:
- 简单易上手:概念清晰(模型、视图、控制器),适合快速开发 UI 驱动的应用(如 CMS、管理后台)。
- UI 与逻辑解耦:视图可独立修改,控制器处理交互逻辑,模型专注数据,便于前端与后端并行开发。
- 适配快速迭代:适合需求频繁变化的场景(如原型开发),只需调整视图或控制器逻辑。
- 框架支持成熟:主流语言(Java、Python、JavaScript)均有成熟 MVC 框架(Spring MVC、Django、Angular)。
- 缺点:
- 业务逻辑混乱:复杂业务中模型可能沦为 “数据容器”(贫血模型),业务逻辑扩散到控制器,导致代码难以维护。
- 缺乏业务边界:无明确领域划分,大型项目中模型可能包含多个领域的逻辑,形成 “大泥球” 架构。
- 可测试性局限:控制器与模型的耦合可能导致单元测试依赖外部资源(如数据库),测试成本高。
- 扩展性不足:当业务复杂度上升时,MVC 架构难以支撑,需引入额外模式(如服务层、仓储)补充。
最后:DDD如果做得差,如:领域划分不清、实体封装不到位、太追求设计等,会导致项目难落地。想要做好,要了解业务,并预测业务变化。
全部评论