领域驱动设计(DDD)学习笔记与应用实践

前言

在深入学习领域驱动设计(Domain-Driven Design,简称DDD)的过程中,我参考了《极客时间的领域驱动设计课程》以及B站上的分享视频,结合自己的理解进行了笔记整理,并尝试将其应用到业务系统中。以下是我的学习笔记和应用心得。

资料来源- 《极客时间的领域驱动设计课程》:一门深入讲解DDD的课程,推荐购买学习。- B站视频分享:DDD领域驱动设计分享,提供直观的学习体验。

学习背景之前的学习中,我曾写过一篇关于DDD的文章,但感觉在实际工作中应用DDD仍有一定的难度。因此,我希望通过这次的学习,能够更好地理解和运用DDD。

DDD核心概念- 领域模型:基于业务领域的知识构建的模型,帮助我们更好地理解和设计系统。- 统一语言:开发团队和业务团队之间共享的语言,确保沟通的一致性。- 限界上下文:明确不同模型的边界,避免概念的混淆。

DDD实践步骤1. 领域分析:识别业务领域的关键概念和实体。2. 模型构建:基于领域分析的结果构建领域模型。3. 统一语言的建立:确保开发和业务团队使用统一的语言进行沟通。4. 限界上下文的划分:明确不同模型的适用范围和边界。

应用场景- 在业务系统中,通过DDD的方法可以更好地理解业务需求,设计出更符合业务的系统架构。- DDD也有助于团队成员之间的沟通,提高开发效率。

结语通过这次学习,我对DDD有了更深入的理解,并尝试将其应用到实际工作中。希望我的笔记和心得能对同样在学习DDD的你有所帮助。

DDD 设计思想的实践与挑战

在最近的一次团队讨论中,我们意识到虽然大家对领域驱动设计(DDD)都有所了解,但在实际应用中却面临着诸多困难。即使有尝试,也往往缺乏系统性和深度。DDD 本质上是一种设计思想,它在不同人的理解和不同业务场景下的应用会有所差异。我们的目标是追求真理,不断探索和接近事物的本质。

一、架构师在 DDD 体系下的职责

  1. 理解 DDD 核心理念 架构师需要深入理解 DDD 的核心理念,包括领域模型、限界上下文、实体、聚合等概念,并能够将这些理念应用于实际项目中。
  2. 引导团队共识 架构师应引导团队成员对 DDD 理念达成共识,确保团队在设计和开发过程中能够遵循相同的原则和方法。
  3. 设计领域模型 基于对业务的深入理解,架构师负责设计出合理的领域模型,确保模型能够准确反映业务需求和逻辑。
  4. 划分限界上下文 架构师需要识别并划分不同的限界上下文,明确各上下文之间的边界和交互方式。
  5. 持续迭代与优化 架构师应持续对设计进行迭代和优化,以适应业务发展和变化,确保系统的可维护性和可扩展性。
  6. 推动 DDD 落地 架构师不仅要在理论上掌握 DDD,更要在实践中推动其落地,解决实际问题,提高团队的工作效率和项目质量。 通过上述职责的履行,架构师可以有效地将 DDD 设计思想转化为实际的软件架构,为团队和项目带来价值。

1.1、DDD 与微服务设计

1.1.1、熟悉的逻辑架构图

1.1.2、熟悉的接口依赖

1.1.3、熟悉的 DDD 设计

1.1.4、熟悉的 DDD 设计

1.2、DDD 与分层模型设计

1.2.1、六边形架构

图片来源:https://www.jdon.com/ddd/jivejdon/1.html

1.2.2、洋葱架构(简洁架构)

图片来源:https://www.jdon.com/53095

1.2.4、CQRS 架构

CQRS 是命令和查询分离,命令主要实现写入功能,例如新增、修改、删除。

图片来源:https://www.jdon.com/ddd/jivejdon/1.html

1.3、DDD 与业务的理解

1.4 小结

在阅读了上述资料后,我们可能会有一种似曾相识的感觉,但同时又觉得似乎缺少了一些深入的洞见。这种体验非常普遍,即便是许多资深的架构师,他们对于这些概念也有着各自不同的理解。本文将结合作者本人的学习经历和理解,对这些概念进行阐述。不过,随着知识的不断更新和深入,文章内容可能需要进一步的修正和完善。

一、DDD 名词解析

领域驱动设计(Domain-Driven Design, DDD)是一种软件开发方法论,它强调以领域为中心的软件开发过程。在DDD中,有几个核心概念需要我们了解:

  1. 领域(Domain):指的是软件所服务的特定业务领域。2. 子域(Subdomain):领域中更具体的业务领域。3. 界限上下文(Bounded Context):明确定义的领域模型的边界。

二、知识图谱

知识图谱是一种结构化的语义知识库,它通过图的形式存储实体之间的关系。构建知识图谱可以帮助我们更好地组织和理解信息,以下是构建知识图谱的几个关键步骤:

  1. 实体识别:识别出知识图谱中的实体,如人、地点、组织等。2. 关系抽取:确定实体之间的语义关系。3. 图谱构建:将实体和关系以图的形式组织起来。 在构建知识图谱的过程中,我们需要注意以下几点:
  • 确保实体和关系的准确性。- 保持图谱的更新,以反映最新的知识状态。- 利用图谱进行复杂的查询和分析。 通过上述内容,我们对DDD和知识图谱有了更清晰的认识。然而,这些知识仍然需要在实践中不断检验和完善。

架构演进的前提知识

架构演进的背景架构演进是一个持续的过程,它不是一蹴而就的。架构设计是随着业务发展而逐步优化和完善的。每个架构师都深知,一个优秀的架构并非一开始就完美无缺,而是根据实际业务场景不断演化而来。

架构设计原则的重要性尽管架构设计是动态的,但依然存在许多架构设计原则、模式和思想。这些原则是基于对大量业务场景的总结和提炼,它们为架构设计提供了指导和参考。

架构演进的过程架构演进是一个需要时间的过程。它要求架构师在设计初期就考虑到未来可能的变化,以便在业务发展过程中能够灵活应对。这个过程需要不断地评估、调整和优化。

结论架构设计不是一次性的活动,而是一个随着业务发展而不断进化的过程。架构师需要根据业务需求,运用设计原则和模式,逐步构建和完善架构。

架构演进的策略- 持续评估:定期审视现有架构,确保其满足当前和未来的业务需求。- 灵活调整:在业务发展过程中,根据需要对架构进行调整。- 优化迭代:通过不断的迭代,优化架构的性能和可扩展性。- 经验总结:从实践中学习,总结经验教训,为后续的架构演进提供参考。

架构演进的挑战- 技术更新:随着技术的快速迭代,架构需要适应新技术的发展。- 业务变化:业务需求的不断变化对架构的灵活性和可扩展性提出了更高要求。- 团队协作:架构演进需要团队成员之间的紧密合作和有效沟通。

架构演进的实践- 案例分析:研究其他成功或失败的架构演进案例,吸取经验。- 技术探索:积极探索新技术,评估其对现有架构的影响。- 架构评审:定期进行架构评审,确保架构与业务目标保持一致。

架构演进的未来架构演进是一个永无止境的过程。随着业务的发展和技术的进步,架构师需要不断地学习和适应,以构建更加健壮和灵活的系统。

这里的架构还可以再借用下 dubbo 官网的架构

微服务架构与DDD的关联

微服务架构与领域驱动设计(DDD)的结合是一种自然而有效的实践,它们共同促进了复杂系统的可管理性和可扩展性。以下是对这种关联的详细阐述:

1. 微服务架构的演进- 单一应用架构:在网站流量较小时,所有功能部署在一个应用中,以简化操作并降低成本。- 垂直应用架构:随着访问量的增加,将应用拆分为多个独立的应用以提高效率,此时Web框架(MVC)是关键。- 分布式服务架构:面对应用间的交互,将核心业务作为独立服务,形成服务中心,以快速响应市场变化,分布式服务框架(RPC)至关重要。- 流动计算架构:随着服务数量的增加,需要一个调度中心来实时管理集群容量,提高机器利用率,资源调度和治理中心(SOA)成为关键。

2. DDD的引入- 领域模型:DDD强调基于业务领域的模型构建,这为微服务提供了清晰的服务边界和职责定义。- 服务拆分:通过DDD的领域划分,可以将单体服务拆分为多个具有独立业务逻辑的微服务。

3. 阿里架构示例以阿里的商城系统为例,我们可以按照业务功能进行服务拆分:- 商品服务:管理商品信息,包括库存、价格等。- 订单服务:处理订单流程,包括下单、支付、发货等。- 用户服务:管理用户信息和用户行为。

4. 微服务与DDD的结合优势- 独立性:每个微服务负责特定的业务领域,具有高度的独立性和可维护性。- 可扩展性:随着业务的发展,可以独立扩展特定服务,而不影响其他服务。- 灵活性:DDD的模型驱动设计允许快速适应业务变化,实现服务的快速迭代。

结论微服务架构与DDD的结合,为大型复杂系统的开发和维护提供了一种有效的解决方案。通过DDD的领域模型,可以更清晰地定义服务边界,实现服务的独立性和可扩展性,同时流动计算架构的引入,进一步提升了资源的利用效率和系统的响应能力。


在软件开发过程中,随着业务需求的不断增长和变化,系统架构的复杂性也随之增加。为了应对这种复杂性,领域驱动设计(Domain-Driven Design, DDD)和微服务架构(Microservices)成为了两种有效的解决方案。以下是对这两种方法的详细解析:

领域驱动设计(DDD)DDD 是一种设计思想,它强调从业务领域的角度出发,通过以下步骤来简化和控制软件系统的复杂性:

  1. 领域边界划分:DDD 认为,通过明确划分业务领域的边界,可以更好地理解和组织业务需求。2. 构建通用语言:在团队内部建立一种通用语言,以确保所有成员对业务概念有统一的理解。3. 领域模型建立:基于业务抽象,构建领域模型,这些模型能够反映业务实体、规则和行为。4. 业务与代码逻辑一致性:保持业务逻辑与代码实现的一致性,以便于系统的维护和演进。 DDD 不是一种具体的架构,而是一种指导架构设计的思维方式。它通过简化业务领域,帮助设计清晰的领域和应用边界,从而实现架构的平滑演进。

微服务架构(Microservices)与 DDD 专注于设计思想不同,微服务架构关注的是系统的运行时特性:

  1. 进程间通信:微服务架构强调服务之间的轻量级通信机制。2. 容错和故障隔离:每个服务独立运行,具备容错能力,故障不会影响到整个系统。3. 去中心化数据管理:每个服务管理自己的数据库,实现数据的自治。4. 去中心化服务治理:服务的独立开发、测试、构建和部署,无需依赖其他服务。 微服务架构通过将大型复杂系统拆分成多个小型、独立的服务,提高了系统的可维护性和可扩展性。

DDD 架构师的工作DDD 架构师在设计系统时,需要关注以下几个方面:

  • 明确业务需求和领域模型。- 设计清晰的领域边界和应用边界。- 促进团队内部的通用语言建立。- 确保业务逻辑与代码实现的一致性。 通过这些工作,DDD 架构师能够引导团队构建出既符合业务需求又易于维护和演进的软件系统。

DDD 设计概述

DDD(领域驱动设计)是一种软件开发方法论,它强调以业务领域为中心进行软件设计。DDD 包含两个主要部分:战略设计和战术设计。

战略设计战略设计关注于业务视角,其核心任务包括:

  • 建立业务领域模型:明确业务流程和业务实体之间的关系。- 划分领域边界:界定不同业务领域的界限,以便于管理和维护。- 建立通用语言的限界上下文:通过通用语言来定义领域内的术语和概念,确保团队成员之间的沟通一致性。- 微服务设计参考:限界上下文可以作为微服务设计的参考边界,帮助划分服务的职责范围。

战术设计战术设计则侧重于技术实现,主要任务包括:

  • 聚合根:定义领域中的关键实体,作为数据修改的起点。- 实体:具有唯一标识和生命周期的领域对象。- 值对象:描述领域中不具有唯一标识的数据结构。- 领域服务:执行领域逻辑,不直接存储状态的服务。- 应用服务:协调领域模型和基础设施,处理应用程序的业务逻辑。- 资源库:负责数据的持久化和检索。

DDD 与项目管理DDD 方法论在项目管理中的应用,可以帮助团队更好地理解业务需求,明确项目目标,从而提高软件开发的效率和质量。

总结DDD 设计方法论通过战略和战术设计的结合,为软件开发提供了一种以业务为中心的系统化方法。通过这种设计,可以确保软件系统更好地满足业务需求,同时提高系统的可维护性和可扩展性。

实施领域模型划分的三步策略

第一步:梳理业务过程在进行领域模型划分时,首先需要通过事件风暴来识别业务流程中的关键要素,包括用户操作、事件以及外部依赖关系。这些要素将帮助我们识别出领域中的实体和对象。

第二步:构建聚合接下来,基于领域实体之间的业务关联性,将紧密相关的实体组合起来形成聚合。在聚合中,需要明确聚合根、值对象和实体。聚合之间的边界是逻辑上的,通常用虚线表示,意味着它们在同一个微服务实例中运行。

第三步:定义限界上下文最后,根据业务逻辑和语义边界,将一个或多个聚合归类到一个限界上下文中,形成完整的领域模型。限界上下文之间的边界是物理上的,可能代表着未来的微服务边界。不同限界上下文的领域逻辑运行在不同的微服务实例中,物理上相互独立,通常用实线表示。

注意:在划分领域模型时,需要考虑业务的紧密性、逻辑的一致性以及物理上的隔离性,确保每个微服务都能独立运作且易于维护。

领域驱动设计(DDD)核心知识体系解析

领域驱动设计(DDD)是一种软件开发方法,旨在通过领域模型来解决复杂业务问题。以下是DDD的核心知识体系的梳理:

1. 领域细分领域细分是DDD的基石,它通过将问题域逐级细分,降低业务理解和系统实现的复杂度。细分包括:

  • 子域:包括核心域、通用域和支撑域。- 限界上下文:定义特定子域的边界和上下文。- 聚合:由聚合根、值对象和实体组成,是数据一致性的单元。

子域详解- 核心域:决定产品和公司核心竞争力的子域,是业务成功的主要因素。- 通用域:提供多个子域通用的功能,没有太多个性化需求。- 支撑域:虽然必需,但不包含核心竞争力或通用功能。

2. 定义领域内容在DDD的分析和设计过程中,确保术语统一至关重要。以下是定义领域内容的关键步骤:

  • 确保限界上下文内的术语一致性。- 在代码模型设计时,建立领域对象与代码对象的一一映射。- 实现业务模型与代码模型的一致性,统一业务语言和代码语言。

3. 领域模型的重要性领域模型不仅映射成微服务,而且反映了业务的复杂性和需求。通过构建合适的领域模型,可以更有效地解决问题域内的问题,从而提高系统的可维护性和扩展性。

4. 领域驱动设计的应用DDD的应用有助于公司根据不同子域的功能属性和重要性,采取不同的资源投入和建设策略。这不仅影响公司的技术决策,也关系到业务发展的方向。

通过上述内容的梳理,我们可以更清晰地理解DDD的核心知识体系,并将其应用于实际的软件开发过程中。

微服务与限界上下文理论解析

在微服务架构设计中,限界上下文是一个关键概念,它定义了微服务的边界和功能范围。以下是对限界上下文和微服务映射的理论理解及其在保险行业中的应用案例。

1. 限界上下文定义限界上下文是微服务架构中用于划分不同服务边界的概念。它帮助我们确定服务的职责范围,确保服务的独立性和可维护性。

2. 领域模型映射将领域模型映射到微服务中,是实现从问题域到解决方案的关键步骤。这涉及到对业务流程和数据模型的深入理解。

3. 保险行业案例分析以保险行业为例,业务流程可以概括为四个主要步骤:核保、支付、承保和理赔。每个步骤都可以视为一个独立的限界上下文,映射到相应的微服务中。

  • 核保:对应投保过程,是风险评估和定价的关键环节。- 支付:涉及保费的收取和支付流程的实现。- 承保:即保单管理,是保险合同的生成和维护过程。- 理赔:是保险事故发生后的赔付处理流程。

4. 微服务架构的优势通过将业务流程分解为独立的微服务,可以提高系统的灵活性和可扩展性,同时降低维护成本和复杂性。

5. 结论理解限界上下文在微服务架构中的重要性,有助于我们更好地设计和实现软件解决方案,特别是在复杂的业务场景如保险行业中。

定义实体与值对象

在领域驱动设计(Domain-Driven Design, DDD)中,实体(Entity)和值对象(Value Object)是构成领域模型的两个基本元素。以下是对它们的详细解释:

实体的业务形态实体在DDD的战略设计阶段扮演重要角色。它们是领域模型中的核心对象,拥有多个属性、操作或行为。在事件风暴中,通过分析命令、操作或事件,可以识别出产生这些行为的业务实体,并根据业务规则将它们与值对象进行聚类,形成聚合。

实体的代码形态在代码层面,实体通过实体类(Entity Class)来表示,这些类包含实体的属性和方法。在DDD中,实体类通常采用充血模型(Rich Model),将与实体相关的所有业务逻辑封装在实体类的方法中。跨实体的领域逻辑则在领域服务中实现。

实体的运行形态实体以领域对象(Domain Object, DO)的形式存在,每个实体对象都有唯一的标识符(ID)。即使实体对象的数据经过多次修改,由于它们拥有相同的ID,它们仍然代表同一个实体。

实体的数据库形态实体的数据库形态可能与领域建模中的实体有所不同,需要根据实际的业务需求和数据库设计原则进行调整。

值对象的定义根据《实现领域驱动设计》一书,值对象是通过其属性值来识别的对象,它将多个相关属性组合成一个概念整体。在DDD中,值对象用于描述领域的特定方面,且没有标识符。

值对象的特点- 无唯一标识:值对象没有唯一的标识符,它们是通过属性值来定义的。- 不变性:一旦创建,值对象的属性通常不会改变。- 可替换性:如果两个值对象的属性值相同,则它们可以互换使用。

通过上述解释,我们可以更清晰地理解实体和值对象在DDD中的定义和应用。

2.5.1、 值对象的业务形态

值对象是 DDD 领域模型中的一个基础对象,它跟实体一样都来源于事件风暴所构建的领域模型,都包含了若干个属性,它与实体一起构成聚合

2.5.2、值对象的代码形态

2.5.3、值的运行形态


在领域驱动设计(Domain-Driven Design, DDD)中,数据库形态和聚合的定义是实现业务逻辑的关键部分。以下是对上述内容的重新编写:

2.5.4 数据库形态设计在进行领域建模时,我们可以通过识别并设计值对象来优化数据库结构。值对象(Value Object)是一种无唯一标识的对象,它通过属性值来表达其业务意义。通过将值对象嵌入到实体中,我们可以减少数据库中的表数量,从而简化数据库设计,同时保留对象的业务含义。

值对象的作用- 简化数据库结构:通过嵌入值对象,减少表的数量,降低数据库复杂性。- 保留业务涵义:值对象通过其属性值来表达业务意义,有助于保持数据的业务相关性。

2.6 聚合的定义在DDD的分层架构中,领域层是实现核心业务逻辑的关键。聚合(Aggregate)是领域层的一个单元,由多个实体(Entity)和值对象组成,它们共同实现一个业务逻辑的高内聚。

聚合的特点- 充血模型:聚合内的实体采用充血模型(Rich Model)实现,即实体具备完成其业务功能的所有必要行为。- 业务逻辑的高内聚:聚合确保了相关业务逻辑的集中处理,提高了代码的可维护性和可读性。

通过上述内容的重新组织,我们可以看到,在DDD中,无论是数据库形态的设计还是聚合的定义,都强调了业务逻辑的实现和数据结构的优化。

2.7、如何定义聚合根

聚合根主要目的是为了避免由于复杂数据模型缺少统一的业务规则控制,而导致聚合、实体之间数据不一致的问题。

外部对象不能直接访问聚合和实体状态。