Skip to content

面向领域驱动设计 —— Domain Driver Design #14

Description

@xlorne

领域驱动设计(DDD)

2026-08-18 lorne

DDD让业务决定模型,让模型组织软件,让数据与技术服务于业务。

它是什么?

领域驱动设计是一种以业务为出发点、以领域模型为核心组织软件设计的方法论。它将业务问题抽象为领域模型,通过模型分析业务、表达规则和解决问题,并以此指导业务、数据与技术的组织方式。

DDD提供的是软件设计的基本方向和判断标准,而不是一套固定的开发方法。它不规定必须采用某种架构、设计模式、技术框架或实现流程。判断是否符合DDD,关键不在于使用了哪些形式,而在于业务是否得到了准确表达,领域模型是否真正承担了业务职责,以及数据和技术是否围绕业务提供支撑。

在本文采用的实践方式中,领域模型通过面向对象设计进行表达,并通过适当的架构设计将业务、数据与技术解耦。这样做不是为了遵守某种DDD规范,而是为了保护领域模型,使数据归数据、技术归技术、业务归业务,各司其职、低耦合协作。

以“取消订单”为例,订单能否取消、取消后如何改变状态、是否需要退款,属于业务规则,应当由订单领域模型决定;如何查询和保存订单属于数据问题,应当由数据层负责;如何调用支付平台完成退款属于技术问题,应当由基础设施负责。

因此,DDD并不是简单地将数据库表包装成类,而是让领域模型真正承担业务职责。订单不再只是一个保存数据的对象,而是一个能够判断是否允许取消、执行状态变化并产生相应业务结果的业务对象。

它解决了什么?

1. 更容易掌控业务复杂度

领域驱动设计将业务、数据与技术进行解耦,减少彼此之间的依赖,使复杂度被限制在清晰的边界内。再通过面向对象设计对业务进行抽象和建模,使领域模型具备更好的表达力与适应能力,从而更容易应对复杂且持续变化的业务。

例如,订单可能存在“待付款可以直接取消”“已付款取消需要退款”“已发货不能取消”等规则。如果这些判断分散在接口、数据库脚本和流程代码中,规则越多,系统就越难理解和修改。DDD将这些规则集中到订单模型中,使开发者可以直接围绕订单的状态和行为处理变化。

DDD并没有消除业务本身的复杂度,而是将原本分散、隐藏的复杂度集中到业务模型中,使其能够被明确地表达、理解和控制。

2. 更容易保障软件质量

持续应对变化的前提,是建立完善的自动化回归测试机制。领域驱动设计将业务、数据和技术进行解耦,使每一部分都可以围绕自身职责进行独立、明确的测试,从而提高整个系统的可测试性。

领域模型的测试专注于业务规则,只需要构造业务对象并验证其行为,不需要依赖数据库和外部系统;数据层剥离业务逻辑后,可以专注测试数据的存储、查询、映射和事务;技术层则可以专注测试接口调用、消息传递以及外部系统的集成。

例如,在测试“取消订单”时,领域模型负责验证不同状态下是否允许取消;数据层负责验证取消后的订单状态能否被正确保存;技术层负责验证退款请求能否被正确发送到支付平台。

这种设计不仅让业务规则更容易测试,也使数据和技术从复杂的业务场景中解放出来,转变为职责清晰的功能性测试。每一部分都能围绕自身职责进行验证,使问题更容易被发现和定位,并共同构成完整的自动化回归测试体系,从而保障软件持续演进的质量。

3. 更容易沉淀和复用业务能力

领域驱动设计在持续落地的过程中,沉淀的是包含业务规则和行为的领域模型,并可以进一步形成独立的业务组件。由于领域模型不直接依赖具体的数据结构和技术框架,因此更容易在业务语义相同的系统中复用和持续演进。

例如,经过长期完善的订单模型,可能已经包含金额计算、状态流转、取消、退款和履约等能力。当其他系统需要相同的订单能力时,可以复用这些经过验证的模型和组件,再根据新系统使用的数据库、支付平台和消息系统实现相应的技术适配。

需要注意的是,复用的前提是两个系统对业务的定义基本一致。DDD首先复用的是业务知识、模型和规则,在业务语义一致的情况下,才进一步复用具体代码。

它不是什么?

1. DDD不是一种技术框架

DDD不是某个开发框架、类库或者固定的代码结构,而是一种以业务为核心组织软件的设计思想。

技术框架负责解决程序如何运行,DDD负责解决业务如何被理解、建模和实现。框架可以被替换,数据库可以被更换,但领域模型所表达的业务规则应当保持相对稳定。

因此,使用了某种分层框架不等于使用了DDD,没有使用特定框架也不代表无法实践DDD。

2. DDD不是四层架构

DDD经常采用用户界面层、应用层、领域层和基础设施层进行架构分层,但DDD本身并不等于四层架构。

四层架构的作用,是划分系统职责并隔离技术细节:用户界面层负责接收请求,应用层负责组织业务流程,领域层负责实现业务规则,基础设施层负责数据库、消息和外部系统等技术能力。它是保护领域模型的一种架构手段,而不是DDD的定义。

DDD也可以通过六边形架构、整洁架构或者其他架构形式实现。采用哪种架构并不重要,重要的是业务是否由领域模型表达,以及数据和技术是否被限制在清晰的边界之外。

因此,项目采用了四层架构,不代表它实现了DDD;项目没有采用标准的四层结构,也不代表它不是DDD。

3. DDD不是一套规范和标准

DDD不是一套必须严格遵守的规范,也不存在一种唯一正确的实现方式。

实体、值对象、聚合、仓储、领域服务、四层架构和六边形架构,都是帮助开发者建立或保护领域模型的可选工具,而不是判断一个项目是否采用DDD的标准答案。

如果某种更简单的设计已经能够让业务得到准确表达,就没有必要为了形式完整而引入更多概念;如果现有设计无法承载不断增长的业务复杂度,就应当引入更合适的建模和架构手段。

判断是否实践了DDD,不应当看项目使用了多少DDD术语,而应当看软件是否真正以业务模型为核心。

4. DDD不是复杂系统的专属方案

很多人认为,简单的CRUD应用不适合DDD,因为它会增加额外的设计和开发成本。我并不完全认同这种观点。

无论项目大小,都需要面对代码耦合、质量保障和持续维护的问题。小项目今天可能只有简单的增删改查,但随着业务规则不断增加,如果代码始终围绕数据库组织,同样会逐渐变得难以理解和修改。

掌握DDD并不意味着必须在每个项目中使用完全相同的设计。简单项目可以采用轻量的领域模型和分层方式,复杂项目则需要更明确的业务边界和更完整的建模方法。

项目大小决定的是DDD落地的深度,而不是是否需要业务建模、职责分离和质量保障。

5. DDD不是设计模式的堆积

实体、值对象、聚合、仓储和领域服务都是实现领域模型的工具,但使用了这些概念并不代表真正实践了DDD。

如果只是机械地增加类和接口,却没有用模型准确表达业务,那么这些设计只会增加系统的形式和复杂度。

DDD的重点不是使用了多少设计模式,而是业务规则是否得到了清晰、准确和内聚的表达。需要什么就使用什么,不需要的设计不应为了形式完整而强行加入。

6. DDD不是把数据库表转换成类

将一张数据库表对应成一个实体类,本质上仍然是数据建模,而不是领域建模。

数据对象表达的是数据如何存储,领域对象表达的是业务如何运行。领域对象不仅包含数据,还应当包含业务规则、状态变化和行为约束。

DDD不是围绕数据库表编写业务代码,而是先建立业务模型,再决定如何保存模型产生的数据。

7. DDD不是一次完成、永不变化的设计

领域模型不是在项目开始时一次设计完成的静态产物。随着团队对业务理解的加深,以及业务本身不断变化,领域模型也需要持续调整和演进。

因此,DDD不是追求一开始就设计出完美模型,而是在开发过程中不断发现业务、验证模型和修正表达,逐步让软件结构接近真实业务。

Vibe Coding时代,DDD的价值在哪里?

Vibe Coding解决了代码快速生成的问题,但要真正用于复杂系统,还必须解决生成结果如何验证、已有能力如何复用,以及系统如何持续演进的问题。

DDD在Vibe coding时代提供的核心价值,正是让Vibe Coding具备可测试、可复用和可持续的开发能力。

1. 可测试:建立自我检测机制

Vibe Coding生成的代码是否正确,不能只依赖人工阅读或功能是否能够运行,而需要通过自动化测试进行验证。

DDD将业务规则集中在独立的领域模型中,使AI可以针对业务行为生成和执行测试,并根据测试结果持续修正代码。测试由此成为Vibe Coding的自我检测机制,为代码生成建立稳定的质量反馈闭环。

2. 可复用:同时提升效率与质量

如果每次开发都让AI重新生成相同的业务逻辑,不仅浪费效率,也容易产生不同的实现和新的错误。

DDD将业务规则沉淀为领域模型和业务组件。经过测试验证的模型可以被重复使用,使AI能够基于已有能力进行组合和扩展。复用减少了重复开发,也减少了重复犯错,因此能够同时提升开发效率和软件质量。

3. 可持续:支撑复杂系统开发

复杂系统不是一次生成完成的,而是在持续变化中逐步演进形成的。

DDD通过稳定的领域模型、清晰的业务边界以及业务与技术的分离,控制代码持续生成所带来的混乱和复杂度。它使AI能够在明确的范围内理解、修改和扩展系统,避免局部变化不断影响整体。

因此,可持续性是Vibe Coding进入复杂系统开发的关键。没有可持续的模型和边界,Vibe Coding只能快速完成局部功能;具备可持续能力之后,它才可能参与长期、复杂的软件建设。

总结

DDD不是一种固定的架构、规范或者开发流程,而是一种以业务为出发点、以领域模型为核心组织软件设计的方法论。

DDD本身不限定具体的实现方式。在工程实践中,可以通过面向对象设计实现领域模型,通过适当的架构设计将业务、数据与技术解耦,并通过自动化测试分别验证各自的职责,从而使业务模型能够被理解、验证、复用和持续演进。

进入Vibe Coding时代以后,代码生成会越来越容易,但如何判断代码是否正确、如何避免重复生成,以及如何支撑复杂系统长期演进,将变得更加重要。代码可以快速生成,但经过验证、可以复用并能够持续演进的业务模型,才是软件真正能够长期积累的核心资产。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions