当前位置:网站首页 > API设计与开发 > 正文

ddd领域驱动模型设计(ddd领域驱动开发)



来源:得物技术

目录

一、前言

二、DDD是什么

三、DDD和MVC的比较

四、DDD究竟能带来什么价值

    1. 业务(团队)价值

        1.1 统一语言

        1.2 清晰的边界定义

        1.3 领域能力沉淀和复用

        1.4 面向业务建模

        1.5 设计和代码的等价

    2. 个人价值

        2.1 提升全局视野

        2.2 提升业务sense

        2.3 构建体系化思维

五、DDD缺点

六、核心概念

    1. 战略方法论

        1.4 支撑域

        1.5 限界上下文

    2. 战术方法论

        2.1 实体

        2.3 聚合根

        2.4 聚合

        2.5 领域服务

        2.6 领域事件

七、领域建模

    1. 事件风暴建模

    2. 四色建模

八、建模实例

    1. 梳理业务流程

    2. 建模-概念模型

    3. 建模-领域模型

九、总结

前言

领域驱动设计简称“DDD”,一套“知易行难”的方法论。同时我所工作的这些年,尤其在某大厂做初创项目的那段时间,经常会产生各式各样的“思想碰撞”,特别在设计中台基建类领域时,为了保证充足的扩展性和稳定性,都要好好的“碰撞”一下。虽然在设计过程中,每个人的想法不尽相同,但是最终达成一致的那一刻,每个人的技术思想都会得到提升。
对于DDD,我的观点是,它是一套非常优秀的能提升个人认知高度的方法论。注意,我说的是个人认知,不仅是它所带来的业务和团队价值(它所带来的业务和团队价值会在下面讲)。它的战略设计方法论能很好提升技术人员的全局视野,它的战术设计方法论也能强化个人的技术细节把控力和结构性思维。除此之外,好的DDD设计也反映出一个技术人员对于业务的理解力,往往优秀的领域专家也是半个业务专家
如果你一直困惑于自己究竟该如何提升技术和业务思考能力;如何提升全局视野,提升自己的结构化思维的能力;如何在写了这么多代码,做了这么多需求的情况下,补充系统化的技术理念。如果这些疑惑点你都涉及,那么理解DDD,同时按照DDD的方式去思考和建设,能够为你带来显著的提升。
同时我还要说明下,因为DDD的一些概念比较抽象,会让刚了解的同学产生困惑和模糊感,所以关于战略和战术设计部分,我都会用实际的例子来解释。基于我的经验,最简单的解释才是有效的,所以我会用非常白话的方式表述清楚DDD的实战部分,所以大家不用担心理解问题。

PS:我最后想了下,还是要用个完整的示例来演示下DDD的建模流程,否则光说理论体感太弱,所以文章最后部分,我结合四色建模,加上我自己的过往建模经验,演示了某体验产品0-1建设的具体流程(暂不涉及代码和工程部分),比较喜欢看具体示例的可以直接拖到最后一部分。

DDD是什么

2004年,Eric Evans在发表了一部名为《Domain Driven Design》的著作,其中提及了一套从系统分析到软件设计的方法论——领域驱动设计,简称DDD,领域建模的思想随即铺展开来。
DDD设计的目标是实现软件系统与业务需求的高度契合,提高开发效率和质量,同时也能更好地应对复杂性和变化性。它强调以业务为中心,通过深入领域知识和建立有效的领域模型,来驱动软件设计和开发的整个过程。其中几个核心理论提炼如下:

DDD和MVC的比较

在讲解DDD的价值前,我们先看下DDD这个理念提出来之前,经典的MVC开发模式。
如图,Controller负责业务逻辑的处理,Model代表和持久层交互的数据模型,View层负责视图展示。MVC架构其实很精粹,清晰,对于业务逻辑并不复杂,单一化的场景其实效率是很高的。但是随着业务的多变性和不断复杂化,MVC架构就会暴露以下问题:
于是,为了 解决以上问题,DDD的概念被提了出来。

DDD究竟能带来什么价值

业务(团队)价值

统一语言

同一团队,同一语言。这里的团队不仅是指技术团队,也包含业务、运营、产品、质量等。所有角色的认知语言统一化,不论是在沟通、设计、文档编写、画图、编码等任何环节,都使用同一种语言,保证效率的最大化。

清晰的边界定义

DDD的非常重要的一个概念,就是划分领域和子域的边界,通过边界和核心实体的聚合与建立,定义出清晰的业务范围,避免边界纷争(技术人员应该经常会遇到,明明这个事情属于A范围,但是却要B的应用改造;明明很基础的一个通用能力,AB两个应用各做了一个,改造成本*2,同时还要兜底解决一系列不一致问题)。

领域能力沉淀和复用

业务能力的可复用性,是衡量软件架构设计优秀与否的一个重要指标,强大的复用能力,对于研发效能和业务效能的提升具有很好的正向作用。DDD通过领域能力的沉淀和打磨,使业务和模型统一,也使领域能力得以传承。

面向业务建模

基于现实业务做业务领域的抽象,切分数据和领域(业务)模型,从而降低整个软件复杂度。开发人员应始终聚焦于领域模型,而不是传统理念中关注数据层和接口层的设计。

设计和代码的等价

设计即代码,代码直观表现设计。好的DDD设计,在方案上一句代码都没有,但是却已经清晰的表明了所有的代码实现(尤其在代码结构、层次、定义上会感受得更清楚)。

个人价值

提升全局视野

做领域建模的第一阶段是战略设计,其实就是在做全局业务,流程的梳理,同时对于其中的域划分都要有清晰的标准。要梳理清楚刚说的几项内容,没有全局的认知和思考是不行的,同时当负责人员梳理完这一阶段的时候,潜移默化的其实就已经提升了个人的全局意识和视野了。这也就是我们常说的一个领域专家,也往往是半个业务专家的由来了。

提升业务sense

这个和团队价值中“面向业务建模”具备强关联性,因为DDD是面向业务建模为出发点,所以一切都需要在具备优秀的业务敏感度下进行,没有业务sense也做不好DDD,而做好了DDD,业务sense也一定不错。同时在某大厂接触DDD前期,让我收益最大的一句话是——“业务不吃透,不聊技术”。

构建体系化思维

体系化思维强调将事物、概念和关系组织成一个有条理、有结构的整体,能够更全面、深入地理解问题本质,提供更有效的解决方案(体系化思维其实也是结构化思维的一种呈现,在这里推荐一本书《金字塔思维》,讲的是从过程化思维向结构化思维升级的一些方式方法)。DDD的几个核心概念,要求负责人不能只从单点去看问题,需要从线和面上去深入理解,这点能很好的帮助个人去构建体系化思维的能力。

DDD缺点

任何事物都一定存在正反两面,虽然DDD在构建复杂软件模型上,有天然的优势,但同时这套方法论的缺点也非常明显:

核心概念

DDD战略+战术全景图

DDD的核心理念有两部分,“战略设计,战术设计”,理解清楚了这两部分,其实DDD的精髓也就理解了。但是在这之前,先简单描述下DDD这套方法论的一个完整设计流程。
以上就是最基本的一个的设计流程,要完整的理解这个流程,“战略设计,战术设计”两个阶段尤其关键,接下来先说明战略设计(战略方法论)的核心概念。同时整体的战略和战术设计,光描述有点抽象,我提炼了下整个DDD的分层架构,只保留了最核心的部分,后面理解完了整个理论知识和部分实战后,可以回来再看这张图,会更有体感。

战略方法论

领域

领域(Domain)是指业务问题的特定领域范围,它涉及到特定业务的规则、概念、业务流程等。领域是对业务问题进行分解和组织的基本单位。

子域

子域(Subdomain)是指在一个大的领域中划分出的相对独立的子领域,它通常代表一个独立的业务领域,具有特定的业务逻辑和功能需求。子域可以是整个系统的一个功能模块,也可以是一个独立的业务流程。

通用域

通用域(Generic Domain)是指与特定业务领域无关的通用功能,它是在整个领域中被多个子域所共享和复用的功能。通用域包括一些通用的服务、 工具、组件等,用于支持多个子域的实现。

支撑域

“支撑域”(Supporting Domain)指的是与核心业务的实现和发展密切相关的非业务功能。这些支撑域可以包括安全认证、用户管理、日志记录等在整个系统中被多个子域所共享和使用的基础设施功能。支撑域和通用域概念上有些类似,区分他们的标准简单归纳下的话,支撑域是由外域提供的能力,通用域是本域提供。

限界上下文

“限界上下文”(Bounded Context)则是DDD中的一个重要概念,用于划分和隔离不同的领域或子系统。一个限界上下文指的是一个明确定义了特定业务领域所围绕的边界,它包含了领域模型、业务规则、相关的领域服务和持久化逻辑等。不同的限界上下文之间可以是相互隔离的,每个上下文内部有其自己的语言和模型,但是它们之间也需要通过明确定义的接口进行通信。

小结

在DDD战略设计中,首先需要进行领域建模,即通过与领域专家的合作和深入领域知识的研究,将业务需求转化为领域模型。接下来,根据领域模型进行软件设计和开发,实现业务逻辑和功能。在整个过程中,需要保持与业务专家的紧密合作,不断迭代和验证领域模型的准确性和有效性。下图是体验VOC产品在做设计时的战略架构:

某体验产品的整体战略设计

战术方法论

实体

代表领域中具有唯一身份和生命周期的对象。实体有自己的行为和状态,并通过标识属性进行唯一标识。
充血模型虽然是DDD中推崇的设计模式,通过领域实体,一些关键行为和逻辑其实也能一起拿到了,但是在我的经验中,我更喜欢使用 贫血+充血的混合模型(或者叫充血模型的简化版),因为这里涉及到一个标准的建立问题,如果只用充血模型的话,哪些行为和逻辑该下方到接口服务层,哪些又该收拢到实体中,这里面每个人的理念不一样。而我的标准是, 涉及到持久层和复杂行为都下放到服务层,简单行为放到实体模型中。这样有个好处,随着业务的发展,如果只用充血模型,你的实体会越来越臃肿;如果只有贫血模型,自身又太单薄。所以一部分行为下放到服务层,我可以更细粒度的拆分服务接口,保证更优良的边界和代码可读性,同时也保证了模型自身的健壮性。
最后,不论哪种模型,都没有绝对的好坏,能够很好的定义出设计标准,同时基于自己的理解设计出符合业务扩展的实体和服务就是好的模型。

值对象

代表领域中没有唯一标识的对象,它的相等性是通过值的相等性来判断的,而不是通过标识。比如地址信息,手机号码,标签属性等。

聚合根

聚合根是聚合的根实体,它是一组相关对象的入口点,管理着聚合内其他对象的生命周期和完整性。聚合根通过封装聚合内部的对象,并定义了聚合的一致性边界,确保聚合内的对象之间的关系和约束得到维护。外部对象只能通过聚合根来访问和 操作聚合内的对象,从而保证了聚合的完整性和一致性。

聚合

一组相关对象的集合,由一个根实体(Aggregate Root)作为集合的入口点。聚合定义了一致性边界,通过聚合根管理其内部对象的生命周期和完整性。

领域服务

代表领域中的一些操作或业务逻辑,它不属于特定的实体或值对象,而是为解决特定领域问题提供通用的服务。

领域事件

代表领域中的发生的重要事件,可以用于通知其他领域对象或跨限界上下文进行解耦和协作。

资源库

资源库是用于管理领域对象的 创建、更新和持久化的接口。它实现了将领域对象从内存中存储到持久化介质(如数据库)中,以及从持久化介质中检索对象并还原为领域对象的功能。资源库隐藏了底层的数据访问细节,提供了一致的接口和抽象,使得领域对象的访问和持久化变得简单和统一。

小结

DDD战术设计是在DDD战略设计的基础上,着重于解决如何将业务需求和设计模型有效地映射和实现的具体方法和技术。它的目标是根据战略设计的指导,通过合理的领域建模和架构设计,将领域问题转化为高内聚、低耦合的代码实现,从而更好地满足业务需求。

某体验产品协同域的战术设计

领域建模

到这里,DDD的核心概念基本已经讲述完。基于以上的核心概念,接下来就是DDD最关键的部分——领域建模,它的目的归纳起来就一句话:提炼业务知识,形成统一语言,沉淀领域模型
领域建模的优秀与否,可以说直接决定着本次设计的成败,因为一旦发生建模边界不清晰,实体划分错乱,核心属性没有遵守开闭原则等问题,虽然当下可以正常交付业务,但是对于整个项目的后续发展可以说是灾难性的(之前接触过一个系统,因为一个实体的关键属性在最初设计时,没有制定标准规范,语义不统一,造成使用混乱。最后不得以重新设计,结果造成上游的业务使用方全要配合改造回归,不仅改造成本巨大,同时引发了P级故障)。
我最开始说的“优秀的领域专家也是半个业务专家”,其实就体现在这一环节,好的领域建模,前提一定是深刻理解完业务的,同时再次强调下这个观点:领域建模,是基于现实,但不完全等价于现实
以下是领域建模的交付物:

事件风暴建模

事件风暴(Event Storming)是一种用于快速探索、理解和设计领域模型的合作工作坊技术。它是由Alberto Brandolini于2013年提出的。
事件风暴通过团队协作的方式,以用户的视角来讨论和探索整个业务流程。参与者将自己的理解和知识通过贴在墙上的便利贴上表达出来,核心会围绕着事件去编排整个业务流程。事件可以是任何对业务、系统或用户有意义的事情,包括用户触发的操作、系统的状态转换、通信和消息传递等。这些事件以一种自顶向下的方式,以时间线的形式贴在墙上。随着讨论的深入,团队可以探索和辨识出各种概念、实体、聚合根、资源库、上下文边界、业务流程和事件的关联关系。这有助于更全面地理解整个领域的复杂性,并为后续的领域建模和业务流程设计提供线索和洞察。
事件风暴具有高度可视化的特点,能够促进团队之间的沟通和共享知识。它也可以帮助团队快速理解现有系统的复杂性,并为系统的重构和演进提供指导。此外,事件风暴还可以用作需求分析、业务流程优化和团队协作的工具。
需要注意的是,事件风暴并非一种正式的建模方法,而是一种协作工作坊技术。它可以结合其他建模方法(如领域驱动设计)和工具(如UML、流程图等)来进一步详细和完善领域模型。
在事件风暴中,没有确定的固定语法,但是有一些常用的技术和简写符号,用于记录和表示不同的业务事件和概念。
以下是一些常见的事件风暴语法和符号:
事件风暴的语法并不是严格规定的,而且可以根据团队的需要和偏好进行适当的调整。重点是通过快速的头脑风暴,来协作识别和探索业务领域的关键事件,以促进团队的共享理解和协作。
事件风暴的本质上是通过脑暴的方式,围绕关键领域事件串联整个业务场景的生命周期,通过发散去收集,通过收敛去提炼,要真正把这个方法用好,有两个关键点:
这个方法大家了解下就行,我不展开讲,实战中不常用

四色建模

Peter Coad在他的书《Java Modeling In Color With UML》中,提出了一种与颜色相关的建模方法,被称为Color Modeling。这种方法使用颜色作为一种可视化技巧,用于在领域模型中表示不同的对象和概念。它的目的是通过使用颜色来帮助开发者更清晰地理解和传达模型的结构和关系。
四色建模的思想是通过使用不同的颜色来标识不同的概念和角色,以增加模型的可读性和可理解性。每种颜色都代表一个特定的责任或角色,通过这种方式可以更好地定义和呈现领域模型的各个组成部分,使得开发团队在理解和沟通模型时更加容易。
需要注意的是,四色建模并非DDD的核心概念或原则,它更多地是作为一种模型建立和可视化的辅助工具。DDD更关注于如何基于通用语言、领域模型和限界上下文等概念进行软件系统的设计与开发。
以下是四色模型的语法:
用一句话来概括四色原型就是: 一个什么样的人或物品以某种角色在某个时刻或某段时间内参与某个活动。其中“什么样的”就是DESC,“人或物品”就是PPT,“角色”就是ROLE,而“某个时刻或某个时间段内的某个活动”就是MI。按照这个逻辑,整体流程如下:

建模实例

就结合刚说的四色建模来演示,否则光说还是不够有体感。我以目前负责的“某体验平台(简称VOC)”结合四色建模法来具体演示下。

梳理业务流程

首先描述下VOC的背景和目的,一句话:站在横向和全局的视角, 快速发现用户在得物系产品使用过程中发生的 体验问题,同时 及时定位解决该问题,最终提升用户体验。
以下是之前某大厂的体验中台的目标描述,和VOC类似。
为了能达成上述目标,我们究竟应该怎么做,或者说具备什么样的能力呢,总结下来其实是以下几点:
根据以上的分析思路,我们可以把整体的业务流程梳理出来,同时结合四色建模法,我们把除DESC的其他关键元素体现到流程里(为了便于理解,我画的是比较粗的流程,实际流程会比这个复杂):

体验VOC产品业务流程

从图中可以明显看出来,这个流程的关键四色要素:
有了这个基本的业务流程和关键要素后,接下来进入概念模型的设计阶段。

建模-概念模型

首先什么是概念模型,一句话总结:概念模型是一个高层次的抽象模型,独立于具体实现的领域模型,它关注业务领域的核心概念和关系,以及团队之间的共享理解。
一般我们做建模设计的时候,很多经验丰富的领域专家会略过这一环节,直接抵达领域模型的建模阶段。当然,这并无任何不妥,因为我们最终在做软件开发和编码的时候,必然是基于具体的领域模型去设计的,但是概念模型对于整体建模流程来说,任然非常重要,主要体现在以下几点:
回到主线,基于第一步我们梳理完的业务流程和四色要素,我们做下编排,围绕着上述3个关键时标原型为核心,结合其他几个要素和关系,即可得到体验VOC的完整概念模型。

某体验产品概念模型

建模-领域模型

在完成概念模型的设计后,终于到了我们最终的环节,也是建模流程里最重要的阶段——领域建模。具体的领域模型是在概念模型的基础上进行具体的实现 ,除了表述清楚 核心概念和关系外,还需要能够表达非核心的实体关系的能力,同时它还是指导技术实现的标准。基本上完成这个阶段后,微服务拆分、代码架构的设计、模块划分、核心流程也就确定了。
我们做领域建模时,一般会按照一级子域做拆分,一般一级子域代表了一个完整的业务域,独立解决一类业务问题。参考“体验VOC产品的整体战略设计”部分,我们划分的是洞察子域,协同子域,预警子域和问题子域,所以理论上会拆分4个微服务应用,同时各自去做自己子域的领域建模。下面我例举其中的协同子域来做演示。
整体的建模思路如下:
第一步: 定义解决标准。首先,协同域的目标是高效的助力业务解决问题,那边这里就涉及到如何解决,用什么样的方案解决,解决的流程是怎么样的,谁来解决。首先要确定这个解决标准,我们抽象为“协同方案”,他的核心就是制定解决标准,包括我刚描述的那一系列要解决的问题
第二步,根据解决标准 定义执行标准。有了解决标准后,具体如何解决,这个时候我们就需要有个根据解决标准(协同方案)履约的载体,他会按照方案上制定的流程,处理人,解决方式等去流转,这个载体我们抽象为“协同单”
第三步,围绕着上述两个标准, 去完善域边界,实体关键属性,周边实体和关系网。比如,协同方案里的流程,我们是希望抽象成独立模版做复用性,还是一个方案就代表了一个流程(协同流程)?协同单履约当中的所有记录是否需要留痕和外化,那是否需要提炼一个服务记录的概念(协同记录)?流转里的内容呈现是否需要单独抽出来,做成业务可自定义配置化(表单模版)?协同方案和协同单应该是怎么样的关系?等等这所有的业务逻辑,都需要反映到领域模型中表达出来。
最终以上三步完成后,整个协同域的领域模型也就基本确认好了。因为协同域不复杂,领域模型结合实际做了简化,所以就没有表示核心的领域服务,限界上下文等概念。具体呈现如下:

总结

对于领域驱动设计来说,应该遵循一个道理:不拘于形式(有点类似电影里的,剑客最高的境界是身边无剑,但是任何所见皆可为剑的感觉)。文章的前面部分,我讲了许多的概念:聚合根、值对象、领域事件、限界上下文等,但是实际设计开发过程中,并不需要照搬全套的体现出来,只要能够表达清楚核心的实体和关系、清晰的边界和合理的扩展性即是好的领域设计。当然这篇文章主要是理论部分,实战部分我还是想先把战术设计的全貌先展现一遍,最终再做精简,这样可以既知全貌,却不教条
同时我再强调下,合格的技术专家一定是半个业务专家,而DDD这套方法论,可以让技术同学很好的去全局理解业务形态,同时以结构化的思维去抽象业务概念,既能提升全局的认知高度和架构能力,也能加强细节把控力,所以它是一套很好的软件设计复杂性解决之道
最后回到最初那个问题,一个FBI(数据看板系统),一个电商交易系统,它们都适合用DDD吗,为什么?
欢迎各位同学评论交流。
到此这篇ddd领域驱动模型设计(ddd领域驱动开发)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 单片机设计与开发大学组(单片机设计与开发大学组三等奖)2025-03-31 17:36:05
  • 单片机设计报告设计要求(单片机设计报告设计要求怎么写)2025-03-31 17:36:05
  • win32api手册(win32 api手册)2025-03-31 17:36:05
  • 调用天气api接口(调用天气api接口失败)2025-03-31 17:36:05
  • 51单片机设计实例(51单片机课程设计实例)2025-03-31 17:36:05
  • 行为驱动设计(行为驱动理论)2025-03-31 17:36:05
  • 配置中心设计(配置中心设计流程)2025-03-31 17:36:05
  • 字体图标设计软件(字体图标设计软件下载)2025-03-31 17:36:05
  • 单片机电子钟设计简易时钟(单片机电子时钟设计思路)2025-03-31 17:36:05
  • 单片机设计(单片机设计开发挑战赛)2025-03-31 17:36:05
  • 全屏图片