文章导航
背景
在现代软件开发中,领域驱动设计(Domain-Driven Design, DDD)已成为应对复杂业务系统的利器。由Eric Evans在其经典著作《领域驱动设计》中提出,DDD强调将业务领域的知识融入到软件模型中。
历史上,许多人认为需求分析的重点在于理解用户需求,而软件实现则侧重于技术架构、算法和数据库等技术细节。尽管人们普遍认可软件实现是需求分析的延续,但缺乏明确的指导方针来说明两者之间的具体衔接方式。这种缺乏清晰指引的情况导致需求分析和软件实现之间出现了脱节,分析活动的成果难以顺利转化为实际的系统实现。
问题空间
问题空间指的是需要解决的业务问题和需求。在这个阶段,开发团队与业务专家合作,深入理解业务领域,识别关键问题和需求。问题空间的核心任务是建立一个清晰的领域模型,这个模型能够准确反映业务需求。
解决方案空间
解决方案空间则是指将问题空间中的领域模型转化为实际的软件实现。在这个阶段,开发团队基于领域模型设计和实现系统的架构、组件和功能。解决方案空间的核心任务是将抽象的业务模型具体化为可运行的代码和系统。
桥接问题空间和解决方案空间
领域驱动设计通过明确的问题空间和解决方案空间,并在两者之间建立清晰的连接,解决了传统软件开发中需求分析和实现之间的断裂问题。DDD的方法论指导团队从业务需求出发,逐步构建领域模型,并将其转化为高质量的软件实现,从而提高了软件开发的效率和质量。
领域驱动设计的基本思想:解决方案空间应该和问题空间保持一致。
概念
为了更深入地理解领域驱动设计(Domain-Driven Design, DDD),我们需要掌握其核心概念,这些概念主要包括两种设计模式:战术模式和战略模式。
战术设计
图为为领域模型的战术设计
构造块
这些是DDD的基本元素,用于构建领域模型。
实体
实体(Entity)是领域驱动设计中的一个关键概念,它代表了一类重要的业务对象。在业务系统的演进过程中,实体的状态会发生变化。例如,在电商系统中,订单和支付单是非常重要的业务对象。每个实体都需要一个唯一标识(ID),通常生成一个与业务无关的唯一标识符(如UUID)来作为实体的ID,而不是使用具有业务意义的标识符(如手机号或身份证号)。这是因为业务相关的标识符可能会变更或重复,无法保证唯一性和稳定性。生成与业务无关的唯一标识符,可以确保实体在系统中的唯一性和一致性,避免潜在的业务逻辑冲突和错误。
值对象
值对象(Value Object)在领域驱动设计中虽然不如实体(Entity)那样重要,但在描述业务概念时是必不可少的。值对象没有唯一标识,它们主要用于表示某种属性或特征,从而为实体提供更丰富的业务含义。值对象通常是不可变的,且在业务逻辑中可以被复用。例如,在电商系统中,地址可以作为一个值对象来描述订单的配送信息。尽管地址本身没有唯一标识,但它对订单实体的业务描述至关重要。
在实现上,尽量把值对象实现为不可变对象
领域服务
领域服务(Domain Service)是领域驱动设计中的一个重要概念。领域服务自身不包含数据,而是用于表达某种业务计算逻辑或业务策略。之所以称其为领域服务,是因为它们属于领域层,用于处理那些不适合放在实体或值对象中的业务逻辑。这些服务封装了复杂的业务操作,确保业务规则在系统中得到一致的应用。通过将业务逻辑集中在领域服务中,可以提高代码的可读性和可维护性,同时保持领域模型的简洁性和清晰度。
领域服务是无状态的
领域事件
领域事件(Domain Event)是指在领域中发生的重要事件,它描述了发生了什么,而不是命令系统去做什么。尽管不使用领域事件也能完整地描述业务概念,但领域事件是一个极为有力的工具。引入领域事件后,无论是在需求分析阶段还是在架构设计阶段,都可以带来更大的益处。
构造模块
用于组织和管理领域模型的高级概念。
聚合
Eric Evans在《领域驱动设计》中对聚合的定义如下:“将实体和值对象划分为聚合,并围绕聚合定义边界。选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。作为一个整体来定义聚合的属性和不变性因素,并将其执行责任赋予聚合根或指定的框架机制。
理解下其核心本质就是:聚合通过定义边界和业务完整性,确保了对象间的一致性和协作。
例如:
资源库
用于管理实体和聚合的持久化,提供查找和存储的方法。
工厂
一个聚合通常包含多个对象,这些对象之间的数据可能存在紧密的联系。如果允许分别创建这些对象,就会使聚合作为业务完整性单元的定义面临失败。领域驱动设计中的工厂模式与《设计模式》中的工厂模式本质上是相同的,都是分离了对象的构造和使用,并封装了复杂对象的构造过程。不同之处在于,前者更强调聚合的关注点,确保聚合内的业务逻辑和数据的一致性和完整性。
战略设计
战略设计涉及到更高层次的系统架构设计。它帮助我们解决软件的模块化划分的问题:
- 限界上下文(Bounded Context):确定模型边界。
- 上下文映射(Context Mapping):描绘上下文之间的关系。
限界上下文
Eric Evans在《领域驱动设计》一书中使用细胞做比喻来解释限界上下文(Bounded Context)的概念。细胞是一个功能完备、自成体系的系统,最关键的是它有一层细胞膜,将细胞与外部世界隔离开来。同样,限界上下文本质上是一个自治的小世界,具有完备的职责和清晰的边界。
- 自治性
就像细胞能够独立完成其生物功能,限界上下文也是一个独立运作的模块。它包含所有必要的逻辑、数据和规则来完成其特定的业务职责。在同一个限界上下文内,所有的业务逻辑和数据都是一致的,确保了系统的完整性和可靠性。
- 清晰的边界
细胞膜将细胞与外部环境隔离开来,控制物质进出。同样,限界上下文有明确的边界,将其内部模型与外部隔离。
上下文映射
界限上下文定义了基于领域模型的架构层次的设计分解,而这种分解必然需要集成和协作。上下文映射则总结了界限上下文之间的协作关系模式。
微服务中的应用
领域驱动设计(DDD)与微服务架构(Microservices Architecture)有很强的互补性。DDD为理解和建模复杂业务领域提供了理论框架,而微服务架构将这些模型实现为独立的、自治的服务。通过结合DDD和微服务,可以构建出模块化、可扩展、易于维护的系统。
微服务架构中的DDD
界限上下文
在DDD中,界限上下文定义了模型的边界,并确保在这些边界内的术语和概念具有一致性。在微服务架构中,每个微服务通常映射到一个界限上下文。这意味着每个微服务拥有自己的独立模型和逻辑,不与其他微服务共享数据或逻辑,确保了服务的自治性和一致性。
领域事件
领域事件用于描述领域中发生的重要事件。在微服务架构中,领域事件可以用于服务之间的异步通信。这种事件驱动的方式可以帮助解耦服务,提高系统的可扩展性和弹性。
延展阅读:
谷歌的TimesFM时序预测模型能否革新电商行业的库存管理和销量预测?
如何利用AI大模型知识库提升电商客服的效率和质量:深度探索检索增强生成(RAG)在客服中的应用
咨询方案 获取更多方案详情