领域驱动设计(Domain-Driven Design, DDD)是一种软件设计哲学,它强调基于业务领域的知识来进行软件设计和开发。这种方法不仅帮助开发者构建更符合业务需求的软件,还促进了开发者与业务专家之间的沟通和理解。
本文通过深入浅出的方式介绍领域驱动设计的理论背景、核心概念,并通过一个具体案例来展示其在实际中的应用。
理论背景和核心概念
领域驱动设计最初由Eric Evans在其2004年出版的书籍《域驱动设计:软件核心复杂性的彻底解决方案》中提出。该设计哲学应对的主要是复杂软件项目中业务需求理解的挑战,但是书中的理论和概念很多,能把握这个设计思想的核心深入浅出地解释清楚的文章不多。
核心概念
例如,这个设计思想的核心概念包括但不限于:
- 领域(Domain):指的是软件项目要解决问题的业务领域,是具有共同问题和数据模型的功能区域。
- 领域模型(Domain Model):是对特定领域知识的结构化表示,包括领域中的实体、值对象、聚合、事件、服务等概念。
- 界限上下文(Bounded Context):定义了领域模型的边界,是特定领域模型适用的范围。不同的界限上下文之间通过显式接口进行交互。
- 聚合(Aggregate):是一组具有统一标识的相关对象的集合,聚合内部保持一致性,对外作为数据操作的单元。
- 实体(Entity) 和 值对象(Value Object):实体具有唯一标识,其属性可变;值对象没有唯一标识,通常是不可变的。
- 领域事件(Domain Event):反映领域内发生的重要业务事件。
- 领域服务(Domain Service):在领域模型中实现特定业务操作的无状态方法集合,通常操作多个实体或聚合。
我们不拘泥理解每个概念,大概有个印象就会。
接下来,我们通过具体案例来入手。
具体案例:在线零售商店
假设我们需要为一个在线零售商店开发一个新的订单管理系统。这个系统需要处理订单的创建、支付、发货和退货等功能。
应用领域驱动设计
- 划分界限上下文:我们可以将系统分为几个界限上下文,如“订单管理”、“库存管理”和“支付处理”。
- 定义聚合和实体:
- 订单聚合:包含订单实体、订单项(值对象)、支付信息(值对象)等。
- 商品聚合:包含商品实体和库存实体。
- 领域服务:
- 订单服务:处理订单的创建、支付和取消操作。
- 库存服务:管理库存的增减和验证库存状态。
系统架构图如下:
设计特点
领域驱动设计和常规架构设计有个鲜明的特点,那就是引入了三层抽象。从上往下分别是领域,聚合,实体,即:
- 领域(Domain): 表示软件解决方案所针对的业务范围或问题域。在DDD中,领域是最高层次的抽象,定义了整个系统的业务边界。
- 聚合(Aggregate): 领域中的一组相关对象的集合,它们一起工作来执行某些业务功能。聚合是DDD中的核心设计模式,用于封装业务规则和确保数据一致性。
- 实体(Entity): 在聚合内部,实体是拥有唯一标识符的对象,通常代表具有持续身份和生命周期的业务概念。
简化来说,那就是:
- 领域(Domain): 具有明显特征边界的业务需求集合。
- 聚合(Aggregate): 实现业务需求的具体业务逻辑。(完整来说还包括数据和行为的集合)
- 实体(Entity): 业务逻辑所需的各种数据库和表。(完整来说是不止数据库,实体的特点是其身份保存不变)
领域驱动设计的本质
领域驱动设计鼓励关注核心业务问题,并围绕这些业务问题建立一个富有表达力的领域模型。
多一层抽象
相比传统的设计理念,DDD核心特色是将领域和聚合两个概念分离出来。
传统设计理念中领域和聚合往往是杂糅在一起的。导致系统在新增功能和业务时改动边界不清晰。例如,一个业务对象和其操作可能散布在多个模块或层次中,这使得理解和修改业务规则变得复杂且容易引入错误。
在领域驱动设计中,全新功能的引入可以通过添加新的系统界限,已有功能的迭代可以通过添加新的聚合或修改现有聚合来实现,这种划分能最大程度避免影响到其他无关的部分。
面向领域
相比传统的设计理念,DDD的另一个核心特色是鼓励使用统一的语言模型减少产品团队和研发团队的思维模型差异。
DDD通过使用通用的领域语言(Ubiquitous Language),所有团队成员都可以更清晰地理解系统功能和业务规则,减少了误解和沟通成本。
当产品团队和研发团队使用相同语言沟通,可以明显提高产品需求质量,减少不利于系统实现的需求产生,减少研发团队实现功能的成本,减少研发团队额外的抽象。
结语
笔者对软件架构设计进行过多年的思考和实践,总结出的两个观点,那就是:
贴近产品和现实的抽象是最好的抽象。
用新增代替修改,每次做新需求,新增一个类/模块。
领域驱动设计(DDD)的概念很多,理解难度很大,但是抽丝剥茧后,发现殊途同归。
如果你对架构设计很有兴趣,欢迎进一步阅读:
《从一个案例出发,成为优秀的软件架构师》