DDD之我见:(一)概念介绍

2025-07-06 04:20
413
0

领域驱动设计(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如果做得差,如:领域划分不清、实体封装不到位、太追求设计等,会导致项目难落地。想要做好,要了解业务,并预测业务变化。

 

全部评论