Skip to content

DDD架构

约 3330 字大约 11 分钟

DDD

2025-07-10

http://domain-driven-design.org/zh/ddd-concept-reference.html

https://articles.zsxq.com/id_wmqbj24vcojx.html

领域模型(Domain Model): 领域模型是对特定业务领域知识的精确表述,它包括业务中的实体(Entities)、值对象(Value Objects)、服务(Services)、聚合(Aggregates)、聚合根(Aggregate Roots)等概念。领域模型是DDD的核心,它反映了业务专家的语言和决策。

统一语言(Ubiquitous Language): 统一语言是开发团队与业务专家共同使用的语言,它在整个项目中保持一致。统一语言确保所有人都对业务概念有着相同的理解,减少沟通成本和误解。

限界上下文(Bounded Context): 限界上下文是明确界定的系统边界,在这个边界内部有一套统一的模型和语言。不同的限界上下文之间可能有不同的模型,它们通过上下文映射(Context Mapping)来进行交互和集成。

聚合(Aggregate): 聚合是一组相关对象的集合,它们被视为数据修改的单元。每个聚合都有一个聚合根,它是外部对象与聚合内部对象交互的唯一入口。

领域服务(Domain Services): 当某些行为不自然属于任何实体或值对象时,这些行为可以被定义为领域服务。领域服务通常表示领域中的一些操作或业务逻辑。

应用服务(Application Services): 应用服务是软件的一部分,它们协调领域对象来执行任务。它们负责应用程序的工作流程,但不包含业务规则或知识。

基础设施(Infrastructure): 基础设施包括为领域模型提供持久化机制(如数据库)、消息传递、应用程序的配置等技术组件。

领域事件(Domain Events): 领域事件是领域中发生的有意义的业务事件,它们可以触发其他子系统的反应或流程。

DDD 的目标是通过将软件的关注点集中在核心领域上,并通过丰富的领域模型来管理复杂性,从而提高软件的质量和维护性。DDD 强调与业务专家的紧密合作,以确保软件解决方案能够准确反映业务需求。通过这种方法,软件开发团队可以创建出更加灵活、可扩展且与业务紧密结合的系统。

什么是DDD

DDD 是一种软件设计方法。也就是说 DDD 是指导我们做软件工程设计的一种手段,它提供了用切割工程模型的各类技巧,如;领域、界限上下文、实体、值对象、聚合、工厂、仓储等。通过 DDD 的指导思想,我们可以在前期投入更多的时间,更加合理的规划出可持续迭代的工程设计。

战略设计:主要以应对复杂的业务需求,通过抽象、分治的过程,合理的拆分为独立的多个微服务,从而分而治之。 战术设计:运用领域模型来表达业务概念。通常在不做领域模型设计的架构,也就是通常映射到 MVC 三层架构下,Service + 数据模型的开发模式,会让 Service 扁平的、大量的,平铺出非常复杂的业务逻辑代码

充血模型

充血模型,指将对象的属性信息与行为逻辑聚合到一个类中,常用的手段如在对象内提供属于当前对象的信息校验、拼装缓存Key、不含服务接口调用的逻辑处理等。 使用一个对象时,就顺便拿到这个对象的提供的一系列方法信息,所有使用对象的逻辑方法,都不需要自己再次处理同类逻辑。

领域模型

领域模型,指特定业务领域内,业务规则、策略以及业务流程的抽象和封装。在设计手段上,通过风暴模型拆分领域模块,形成界限上下文。最大的区别在于把原有的众多 Service + 数据模型的方式,拆分为独立的有边界的领域模块。每个领域内创建自身所属的;领域对象(实体、聚合、值对象)、仓储服务(DAO 操作)、工厂、端口适配器Port(调用外部接口的手段)等。

实体、聚合、值对象

实体

依托于持久化层数据以领域服务功能目标为指导设计的领域对象。持久化PO对象是原子类对象,不具有业务语义,而实体对象是具有业务语义且有唯一标识的对象,跟随于领域服务方法的全生命周期对象.

值对象

这个对象在领域服务方法的生命周期过程内是不可变对象,也没有唯一标识。它通常是配合实体对象使用。如为实体对象提供对象属性值的描述,比如;一个公司雇员的级别值对象,一个下单的商品收货的四级地址信息对象。所以在开发值对象的时候,通常不会提供 setter 方法,而是提供构造函数或者 Builder 方法来实例化对象。这个对象通常不会独立作为方法的入参对象,但做可以独立作为出参对象使用。

聚合

聚合是领域模型中的一个关键概念,它是一组具有内聚性的相关对象的集合,这些对象一起工作以执行某些业务规则或操作。聚合定义了一组对象的边界,这些对象可以被视为一个单一的单元进行处理。 当你对数据库的操作需要使用到多个实体时,可以创建聚合对象。一个聚合对象,代表着一个数据库事务,具有事务一致性。聚合中的实体可以由聚合提供创建操作,实体也被称为聚合根对象。一个订单的聚合,会涵盖;下单用户实体对象、订单实体、订单明细实体和订单收货四级地址值对象。而那个作为入参的购物车实体对象,已经被转换为实体对象了。—— 聚合内事务一致性,聚合外最终一致性。

仓储和适配器

封装持久化操作:Repository负责封装所有与数据源交互的操作,如创建、读取、更新和删除(CRUD)操作。这样,领域层的代码就可以避免直接处理数据库或其他存储机制的复杂性。 领域对象的集合管理:Repository通常被视为领域对象的集合,提供了查询和过滤这些对象的方法,使得领域对象的获取和管理更加方便。 抽象接口:Repository定义了一个与持久化机制无关的接口,这使得领域层的代码可以在不同的持久化机制之间切换,而不需要修改业务逻辑。 仓储解耦的手段使用了依赖倒置的设计,所有领域需要的外部服务,不在直接引入外部的服务,而是通过定义接口的方式,让基础设施层实现领域层接口(仓储/适配器)的方式来处理。

领域编排

在 DDD 中,每一个领域都是界限上下文拆分的独立结果,而实现业务流程的功能则需要串联各个领域模块提供一整条链路的完整服务。所以也常说领域内事务一致性,领域外最终一致性。 同时这些领域模块因为是独立的,所以也可以被复用。在不同的场景功能诉求下,可以选择不同的领域模块进行组装,这个过程就像搭积木一样。

触发器

在所有的模型都定义完成后,领域业务被串联了。那么接下来则是使用,而使用的方式可以包括;接口(http/rpc)、消息监听、定时任务等方式,这些方式统一被定义为触发动作。

Domain里面包含什么

领域是指具体业务领域的知识、业务逻辑、数据以及业务规则的集合。它是软件要解决问题的业务环境,通常由一系列子领域组成,每个子领域代表业务中的一个特定部分。

实体(Entity):具有唯一标识的领域对象,代表业务中的实体。

值对象(Value Object):描述领域中的一些特性或概念,没有唯一标识,通常是不可变的。

聚合(Aggregate):一组相关的实体和值对象的集合,它们一起构成一个数据和业务规则的单元。

领域服务(Domain Service):在领域模型中执行特定业务逻辑的无状态服务,通常操作多个实体或聚合。

领域事件(Domain Event):表示领域中发生的重要业务事件,用于解耦系统的不同部分。

仓储(Repository):提供对聚合根的持久化操作,如保存和检索,通常与数据库交互。

领域适配器(Domain Adapter):领域适配器是适配器模式在DDD中的应用,它的目的是使得领域模型能够与外部系统或技术细节进行交互,而不会受到污染。

工厂(Factory):用于创建复杂的聚合或实体,封装创建逻辑。

聚合

聚合是领域模型中的一个关键概念,它是一组具有内聚性的相关对象的集合,这些对象一起工作以执行某些业务规则或操作。聚合定义了一组对象的边界,这些对象可以被视为一个单一的单元进行处理。 聚合内实现事务一致性、聚合外实现最终一致性

用途 封装业务逻辑:聚合通过将相关的对象和操作封装在一起,提供了一个清晰的业务逻辑模型,有助于业务规则的实施和维护。

保证一致性:聚合确保内部状态的一致性,通过定义清晰的边界和规则,聚合可以在内部强制执行业务规则,从而保证数据的一致性。

简化复杂性:聚合通过组织相关的对象,简化了领域模型的复杂性。这有助于开发者更好地理解和扩展系统。

实体

实体(Entity)在领域驱动设计(Domain-Driven Design, DDD)中是一个核心概念,用于表示具有唯一标识的领域对象。 实体 = 唯一标识 + 状态属性 + 行为动作(功能),是DDD中的一个基本构建块,它代表了具有唯一标识的领域对象。实体不仅仅包含数据(状态属性),还包含了相关的行为(功能),并且它的标识在整个生命周期中保持不变。

值对象

在领域驱动设计(Domain-Driven Design, DDD)中,值对象(Value Object)是一个核心概念,用于封装和表示领域中的概念,其特点是它们描述了领域中的某些属性或度量,但不具有唯一标识。

值对象 = 值 + 对象,用于描述对象属性的值,表示具体固定不变的属性值信息。

概念

值对象是由一组属性组成的,它们共同描述了一个领域概念。与实体(Entity)不同,值对象不需要有一个唯一的标识符来区分它们。值对象通常是不可变的,这意味着一旦创建,它们的状态就不应该改变。

例如枚举常量,只会提供一个可读方法,不会提供修改方法。

仓储

Repository(仓储)模式是一种设计模式,它用于将数据访问逻辑封装起来,使得领域层可以通过一个简单、一致的接口来访问聚合根或实体对象。这个模式的关键在于提供了一个抽象的接口,领域层通过这个接口与数据存储层进行交互,而不需要知道背后具体的实现细节。

适配(端口),调用外部接口

Port 在这种架构中代表了应用程序的一个入口或出口点。它定义了一个与外部世界交互的接口,但不关心具体的实现细节。端口可以是驱动端口(Driving Ports,通常是输入端口)或被驱动端口(Driven Ports,通常是输出端口)。

事件,触发消息

领域事件是DDD中的一个关键概念,它代表了领域中发生的一个具有业务意义的事件。这些事件通常是由领域实体或聚合根的状态变化触发的。领域事件不仅仅是数据的变化,它们还承载了业务上下文和业务意图。 类似发布订阅功能

贡献者

  • flycodeuflycodeu

公告板

2025-03-04正式迁移知识库到此项目