前言
1.什么是DDD
领域驱动设计(Domain-Driven Design 简称DDD)历史悠久
2004年著名建模专家eric evans(埃里克埃文斯)发表的他最具影响力的书籍《domain-driven design-tackling complexity in the heart of software》(中文译名:领域驱动设计—软件核心复杂应对之道)一书。标志着DDD这种设计开发和架构方法的诞生
领域驱动设计是书中提出的一种从业务建模到软件设计到的一套方法论。以领域为核心驱动力的设计体系
按照作者在原书中的说法,DDD是来自面向对象的方法学和敏捷软件开发。DDD对它们进行了总结和提炼,使之更容易学习和实践
和其他方法论的不同之处在于,DDD强调开发人员与业务领域专家高效协作,从而共同交付业务价值。从架构设计上说,DDD认为良好的系统架构应该是技术架构和业务领域相互融合的结果,不能脱离业务领域设计技术架构
2.DDD发展历史
3.DDD相关资料
3.为什么需要DDD
在现实中,绝大多数软件开发工作都是围绕现实业务问题而展开的,而业务问题的复杂度是软件开发成功的关键因素之一
学习DDD的根本原因在于软件复杂度针,对软件复杂度,我们的思路是清晰划分软件的关注点,并通过拆分和建模在一定程度上降低系统复杂性。而DDD正是为了降低软件复杂度而诞生的软件设计方法
4.软件复杂度
介绍
任何软件系统的发展都遵循从简单到复杂、从集中到分散的过程。在系统诞生的初期,我们习惯于构建单一、内聚和全功能式的系统,因为这样的系统完全可以满足当前业务的需求。当业务发展到一定阶段,集中化系统开始表现出诸多弊端,功能拆分与服务化思想和实践被引入。而当系统继续演进,团队规模随之增大,由于分工模糊和业务复杂度不断上升,系统架构逐渐被腐化,直到系统不能承受任何改变,进入需要重新拆分的阶段。推倒重来意味着重复从简单到复杂、从集中到分散的整个过程,如下图所示:
系统架构的轮回给人们的启示就是将所有东西放在一起不是一个好的选择,软件系统的关注点应该清晰划分,并能通过功能拆分降低系统复杂性。因此,在本质上,架构的演进过程就是一个解决系统复杂度问题的过程
Jurgen Appelo从理解力与预测能力两个维度分析了复杂系统理论,具体如下图:
注意
软件复杂度体现的是一种客观规律,因为任何一个软件系统都会受到这3个维度的影响,开发人员无法完全避免,但引入一定的设计思想和方法可以降低软件复杂度
5.项目失败的原因
现象
据统计,软件系统建设项目的成功率均在30%以下,超过70%的项目由于项目延期、超出预算、功能缺失等失败甚至取消。站在开发团队的角度,这个数字可能感觉难以置信,但是站在客户的角度,这个数字绝对没有夸张的成分
大多数系统是因为构建系统的业务逻辑而失败的,具体如下图:
本质:为什么构建业务逻辑失败
前言
业务逻辑不就是一些if…else的逻辑吗?这比搭建一个高可用架构简单多了。有些开发者可能有不同意见,他们可能会说,不是构建业务逻辑出了问题,而是它们与技术的结合,也就是实现环节出了问题。那么,接下来的问题就清晰了,我们构建业务逻辑为什么要受到技术因素的影响呢?这合理吗?难道它不是独立于技术而存在的吗?
既然成败的关键在业务逻辑,那么如此高的失败率是因为业务逻辑很复杂吗?是,也不是。毕竟再复杂的业务,在它所在的领域里也是由人来完成的,开发人员的智商应该比较高,没有理由理解不了。出问题的原因并不是业务复杂度本身,而是我们不合理的做法导致我们构建的软件复杂度远远超过了业务本身的复杂度
为什么软件会变得比业务逻辑还复杂,实现模型会比业务模型还麻烦?首先,业务中的复杂关系是不可能在设计中省略的,就好像加密的信息并不会比原始信息量更少一样,前者的复杂度不会比后者低。比如,有多少个关注点、多少条路径、多少组对应关系,都会体现在设计和代码中。如果设计和实现在业务模型上又包裹了一层新的设计,添加了技术组件,那么至少多了一层多对多的对应关系,这就产生了额外的复杂度
领域知识传递失真产生熵增
如下图所示,在业务模型上包裹的每一层设计,都会使复杂度增加一分。这里的设计包括从需求沟通的语言到需求说明书、从需求说明书到概要设计、从概要设计到详细设计的每个环节,因为信息每一次从上层流转到下一层都会被二次包装和转译
技术复杂度与业务复杂度没有分离
复杂度包括两种:业务复杂度和技术复杂度。业务复杂度是指领域固有的计算逻辑、规则约束、判断流程等,不依赖于系统而存在,还包括领域专家与开发团队沟通中会产生的各种不确定性。技术复杂度包括与实现相关的所有内容,比如语言框架、残留系统、技术组件、技术环境等,还包括与领域逻辑不相关的关注点,如交互界面、安全机制等
这两种复杂度单独来对付并不可怕。毕竟开发人员这个群体在抽象和逻辑思维方面不会比其他行业人员差,一个初级程序员学习一个技术框架也没有那么困难。最可怕的是两种复杂度交织在一起的情形,两者之间没有清晰的界面,无法确定哪种业务逻辑散布在散乱组织的代码的何处,这被称为大泥球架构
两类不同的关注点混合起来产生的各种排列组合,往往不是人的脑力所能胜任的,而且也不符合人类关注点分离的思考模式,软件变得难以构建和管理。此时只能通过不断地切割系统,把复杂度限制在一定范围内,就如同潜艇的密封舱一样
难道还能单独地开发业务逻辑吗?是的,这从道理上是说得过去的,只要我们找到合适的载体,完全可以单独构建领域逻辑而不用关心系统采用什么技术。这里并非说撇开编程语言谈构建业务逻辑(事实上,面向对象语言就是我们之后提到的载体),而是说业务逻辑不再和不相关的技术因素相耦合,比如界面、基础设施、既有的技术组件。同时也意味着业务逻辑不应该散布在技术组件的丛林里,它应该有自己的独立性和完整性
既然如此,那么我们想问:能不能找到一种设计方法,业务逻辑可以单独被构建、测试和验收,而不依赖于系统架构的其他部分?
如果有这种方法,那么团队就可以专心应对领域的复杂度,而不被技术复杂度所影响。更大的好处在于我们得到了一个强大的业务逻辑模型,它可以被快速测试和验证,甚至在不同的应用中重用这一逻辑模型
更进一步,研发团队想求证这样一个事实:我们能单独构建、测试和验收业务逻辑,而不依赖于系统架构的其他部分
6.基础知识
问题空间和解空间
介绍
领域本质上是对现实世界问题的一种统称,是一种业务开展的方式,用以体现一个组织所做的事情,以及其中所包含的一切业务范围和所进行的活动。例如,电商系统包含商品、订单、库存和物流等业务概念,而医疗健康系统则关注挂号、就诊、用药、健康报告等业务场景。领域概念的提出不仅从业务的角度体现了系统的功能和价值,而且从技术的角度为人们提供了设计思想
问题空间
我们以一个业务场景为例进行讨论。试想一下日常生活中的生病就医场景。为了完成一次就医过程,用户需要完成预约挂号、向医生述说身体症状、做各种检查并获取报告、根据检查结果进行用药等步骤。如果将这些步骤抽象为一个问题空间,那就是就诊。如果我们设计一个针对这一场景的系统,所有的环节都是为了更好地帮助用户就诊,这是对真实世界的一种表现
解空间
那么,如何针对就诊这个问题空间提供对应的解决方案呢?这就需要引入解空间的概念。解空间代表的是一种逻辑世界,通过设计语言和设计模型来解决真实世界中的问题。下图展示了问题空间和解空间之间的映射关系
建模
那么问题又来了,我们应该如何设计解空间呢?这需要对系统进行建模,从而得到能够指导系统开发的业务模型。系统建模是一个复杂的话题,围绕这一话题,业界也形成了不同的建模方法,而DDD同样在系统建模领域占有重要地位
建模就是为复杂事物画蓝图或建沙盘(建模其实就是构建模型的过程),用更简洁的形式呈现核心逻辑,帮助人们摆脱细节干扰,聚焦关键问题
一般只对客体进行建模,使用UML表达,避免大而全的模型,越简单的模型,越能持续维护
在DDD中常见的建模方法如下:
模型
模型是建模的产物,不是一个真实的东西,是对真实事务的模拟,小到汽车大到航空母舰都可以有自己的模型
模型是对业务(领域某个方面)的抽象和模拟,它通过较为简单的信息结构来代表我们需要理解的复杂事物或系统,并且可以用来解决相关域的问题
建模结果出来的模型如下:
模型分离
模型是针对特定业务问题的,比如订单库存这些概念在电商平台和超市的进销存的模型是完全不一样的,在DDD中推荐把一个模型进行分离,把不同场景的同一个模型进行拆分
举个例子,在支付系统中存在支付与退款的业务逻辑,这两个业务逻辑都要使用支付单这个模型,在传统的开发中这两个业务逻辑会共享一个支付单模型这会导致单个模型的复杂度直线上升(因为这个模型要满足很多业务逻辑),而且当业务逻辑产生差异时,这种单模型问题会更多,在DDD中推崇模型分解的方式,不同的问题域应当使用不同的模型
模型驱动设计
面向模型的分析设计方法,优先通过识别模型来简化业务设计
在设计过程中,以模型为中心,始终维护模型,并基于此指导软件设计
业务模型
下面分析一个完整的业务模型(DDD中的业务模型)应该包含哪些组成部分。我们把业务模型拆分成7个维度,如下图所示:
- 业务描述:业务模型需要通过简洁且通用的语言进行描述,从而确保与模型相关的所有人都能够对模型所代表的业务场景和需求达成统一认识
- 业务拆分:业务场景的复杂度决定了业务模型中功能组件的数量和关联关系,我们需要通过拆分来明确各个组件的功能之间的边界
- 业务对象:在一个业务场景中势必存在一组业务对象,这些业务对象通过一定的交互关系构成具体的业务场景
- 业务规则:在一个业务模型中,内部的核心逻辑通过一系列的业务规则来展现,业务规则代表具体领域的业务价值
- 业务状态:每个业务场景都是有状态的,这些状态构成了业务处理的流程和顺序,也是我们对业务进行建模的重点对象
- 业务数据:所有业务模型都会产生数据,而且业务规则和业务状态的设计在很大程度上是围绕业务数据的处理过程来展开的,我们需要把核心的业务数据进行持久化保存
- 业务外观:一个业务模型需要和客户端、其他业务模块及第三方外部系统进行集成,这就需要开放一定的交互入口,我们把这部分内容称为业务外观
DDD与业务模型
介绍
领域驱动设计针对业务模型为上述7个维度的问题给出了对应的设计方法
DDD主要是通过战略设计和战术设计两大阶段来解决
战略设计
战术设计
总览
请注意,上图中DDD的各个组件并不是位于同一层次的,各个限界上下文都应该包括战术设计的所有技术组件,如下图所示:
领域模型
领域模型是业务概念在程序中的一种表达方式,可以用来设计和理解整个软件结构。面向对象设计中的类概念是领域模型的一种表达方式。与此类似,UML的建模方法也可以应用在对领域模型的表达上。在DDD实践中,领域模型应当尽量简洁,能反应业务概念即可
在传统软件开发中,业务是由数据驱动的,开发人员从数据的角度来规划对象的组织形式,并以面向数据库的方式对这些数据对象进行设计和建模,每个业务对象只包含业务数据和结构的定义,并不具备业务操作能力,这就是所谓的贫血模型
在DDD中领域模型是对业务领域内核心概念、规则、流程及它们之间关系的结构化抽象,是业务知识与逻辑的数字化载体。它不仅包含业务数据,更重要的是封装了业务行为和规则,本质是让软件模型与业务现实保持一致
显然,领域驱动设计的过程与数据驱动完全不同。在DDD中,我们关注的是领域模型对象而非数据本身。虽然以数据作为主要关注点的开发模式也能完成对系统的构建,但我们认为面向领域的模型对象才是通用语言的有效载体。究其原因,很多对象并不能简单地用它们的数据属性来定义,而需要通过一系列的标识和行为来定义。在DDD中,领域模型对象包括三大类型(有的地方也包括其他地方),即聚合、实体和值对象,如下图所示:
数据驱动模式与DDD
我们可以从数据的角度来规划对象的组织形式,并通过面向数据库的方式对这些数据对象进行设计和建模,这种开发模式通常被称为数据驱动模式
它与DDD的开发流程区别如下:
7.DDD组成部分
在上面的软件开发步骤中主要分为业务建模与代码实现这两个步骤,而传统的对于这两个步骤的实现方式在面对复杂系统的时候存在一些问题,所以DDD提出了战略设计与战术设计,战略设计用来实现建模,战术设计通过建模结果来指导如何落地代码,通过战略设计与战术设计来更好的应对复杂系统
- 战略设计:领域专家,设计人员,开发人员,架构师从业务角度出发,用能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型,划分业务边界,建立通用语言的限界上下文,限界上下文可以作为微服务设计的参考边界
- 战术设计:根据领域模型进行技术实现,完成软件的开发以及落地
8.DDD基本原则
介绍
DDD的基本原则是战略、战术和各种模式的基础。这些原则是DDD独特且不可或缺的要素,是使其成为一种革命性设计方法的根本原因。原则必须遵守,否则事物的独特性会消失,优点和收益也会消失
保持语言、模型、代码三者一致
核心概念
- 语言:开发团队与领域专家沟通使用的自然语言。因为它与设计模型、代码是一致的,所以也称为通用语言
- 模型:设计的输出物,是对领域逻辑的精准建模。模型会充分体现具有领域含义的术语和关系。作为通用语言的核心,模型既充当着沟通业务逻辑的媒介,也直接指导开发实现
- 代码:模型和通用语言在实现层的精确表达
介绍
一致也可以理解为领域逻辑、设计、实现三者一致。一致性体现为三者的信息量是一致的,中间没有二次设计,无转译,无熵增。模型和代码(至少是测试代码)应该能被领域专家所阅读和理解。所有人通过模型来理解和交流领域逻辑。三者会相互影响,不断进化,但要实时保持一致
一致性亦体现为语言传达的领域逻辑必须被显式、集中地体现在模型和代码中,而不能被隐式、模糊或分散地表达
解释
语言、模型、代码三者一致是DDD的第一条原则,它们难道不是不同层面的事物吗?如何保持一致?
如果三者是不同层面的事物,那么就是我们前面举例的传统设计方法。从业务沟通到设计,从设计到代码,可能都由不同的人负责和二次设计,每一层都会带来额外的熵增
三者一致的原则,是DDD最有价值的部分。为此,DDD引入了通用语言的概念。三者保持一致,领域才能起到驱动的作用,三者不一致,那么驱动的就不再是领域,而是另有他因了。所以这是DDD最本质的原则
至于如何保持三者一致,离不开通用语言的打造,离不开代码的一些规范
下图是三者一致性与传统方式的对比。可以看到,相对于传统开发模式,DDD语言和代码都统一于单一模型,模型是语言的核心,代码是模型的精确表达
通用语言
保持领域模型的独立性和内聚性
独立性
独立性是我们追求的目标,即领域模型单独被构建,不再与技术复杂度混合在一起,不再与程序的其他关注点(如界面、持久化、集成、通信)混合在一起,从而可以单独被测试、验证和重用。技术上,可以采用六边形架构、依赖倒置的分层架构、资源库模式、接口和晚绑定等来实现
内聚性
内聚性可以理解为有且仅有,有是说相关的领域逻辑要在一起,它可以在模型内,也可以体现在模型的关系中(聚合),但必须显式、集中地体现而不能隐含地散布在各处。同时也仅有相关逻辑,而不含其他不相关关注点的内容
同时,领域模型是业务逻辑的唯一载体和调用入口,同一个逻辑只存在一个地方,而不论是设计还是代码。这是架构原则语义一致性的体现,也是我们能独立测试和验收领域逻辑的保证。(我们不可能测试了一个地方,但系统运行时起作用的却是另一个地方)。事实上,不只是DDD,所有架构设计方法都应该遵守这一原则
核心概念
- 独立性:领域模型可以被独立开发、测试和验收,与系统架构中的其他任何部分都没有依赖关系(只会被依赖)
- 内聚性:关联紧密的业务逻辑要通过模型组织在一起,不宜分散。模型不包含除领域逻辑之外的其他内容,且领域模型是业务逻辑的唯一载体,一处业务逻辑只能存在于一个模型内
总结
| 原则 | 事实 |
|---|---|
| 保持语言、模型、代码三者一致 | 我们能基于业务本身的复杂度来构建软件,而不需要更复杂的方法 |
| 保持领域模型的独立性和内聚性 | 我们能单独构建、测试和验收业务逻辑,而不依赖于系统架构的其他部分 |
9.DDD核心作用
通用语言降低复杂度
语言、模型、代码三者一致,保证了我们以最低的复杂度来构建软件,在业务之上添加任何一层设计都会增加复杂度,传统方式如下:
在功能出来后,领域专家看到成果,团队得到反馈,是在经历了上述重重迷雾之后,再经过环境和数据准备的艰难险阻(可用DevOps克服),才能在浏览器中验证业务逻辑。当然,结果很可能是不理想的,团队在哪一个环节脱节了,我们就不得不再穿越一次迷雾之海。中间任一环节的产出物,都不能用来验证领域逻辑,代码也揭示不了业务目的,导致的结果就是不仅验证领域逻辑困难,灵活性也很差
而在DDD中,我们有通用语言及三者一致的要求,效果如下图:
技术与业务分离降低复杂度
前面已经讲过技术和业务混杂在一起的问题,我们可以通过领域模型的内聚性与独立性是如何解耦业务与技术复杂度的,如下图所示:
从上图中可以看出,领域模型作为沟通的核心,代表了领域专家与技术团队的共识,是他们沟通的媒介,隔离了业务复杂度和技术复杂度
所有业务复杂度在领域模型层面都得到了收敛,我们只需在领域模型的绿洲内畅饮,而无须跨越技术复杂度与业务复杂度的熵之沙漠。团队完全可以先把重心放在领域模型的构建之上,后面再围绕核心领域层搭设系统的技术架构的其他部分,组织相关的开发任务
内聚性保证了相关的业务逻辑都在一起,这个特性使领域专家和开发团队共同打造好领域模型之后,守住这个鸡蛋篮子就可以了。领域专家可以检查业务逻辑的覆盖程度,直接编写验收测试用例,不用担心领域逻辑被遗漏。任何对业务理解有歧义的地方,在领域模型的构建过程中都会得到统一
独立性提供了领域模型的稳定性,技术性变更不会影响到领域模型,可以被很方便地测试,任何人在业务逻辑发生变化时,都可以愉快地启动单元测试套件来测试业务逻辑。在开发人员的指导下,业务人员是可以看懂实现与测试代码的,可以方便地开展静态测试、代码走查。在不同的应用中重用领域逻辑,也有了可能性
10.DDD其他作用
更流畅的团队沟通
领域驱动设计提倡在团队中建设通用语言,团队成员(包括领域专家)和用户之间都采用通用语言进行沟通和交流。通用语言是团队内部达成的共识,采用通用语言进行沟通不会引起歧义,减少了沟通障碍,可以帮助开发人员更好的理解业务需求
更深入的业务理解
领域驱动设计体长开发者加强与领域专家的沟通和合作,在沟通的过程中不断完善通用语言,减少业务理解难度
领域驱动设计通过事件风暴法等领域建模方法,将业务只是建模成领域模型,领域建模的过程也就是理解业务的过程。再领域模型中完整地表达了业务规则和业务过程,业务相关的只是都被封装到领域模型中,得到了很好的抽象和维护,也方便开发者理解业务
更优秀的代码质量
领域驱动设计将业务逻辑封装到领域模型中,可以非常高效和方便地对业务代码进行测试,结合测试驱动开发(TDD),静态代码分析等,可以很好地提高代码的质量
此外,领域驱动设计还提供了一些列的模式,如实体,值对象,聚合,仓储,领域事件等可,可以帮助开发人员处理复杂的业务场景,提高系统的可扩展性和灵活性
更从容地应对需求变更
在传统的软件开发过程中,需求变更往往意味着代码的大规模修改,甚至需要重新设计整个系统,给软件的顺利交付带来风险
在领域驱动设计中,业务代码和基础设施操作是分离的。代码是领域模型的实现,而领域模型和业务逻辑之间存在较强的映射关系。再变更业务需求时,由于开发者只需要关注领域模型的调整,因此可以将业务逻辑变更的影响范围控制在领域模型内。而对于领域模型以外的技术实现细节,即使技术实现方案产生了变更,也不会对领域模型造成影响
由此可见,领域驱动设计可以使开发者更从容地应对需求变更
更高效的开发效率
领域驱动设计通过将复杂业务逻辑和技术性的基础设施操作分离,使开发人员能够更专注于业务需求的实现,避免了对基础设施操作的过度关注。这种聚焦于业务的开发方式能够提高开发效率,减少反攻和变更频次
11.DDD的困境
介绍
领域驱动设计理论自从被提出以来就备受业界关注,并持续受到关注。随着微服务时代的到来,领域驱动设计的重要性更加凸显。越来越多的公司开始关注到领域驱动设计,并将其应用于实际项目中
然而,与业界的火爆程度相比,领域驱动设计的落地现状则稍显尴尬,主要体现在以下几个方面
没有业界认可的开发标准
领域驱动设计的理念和方法非常抽象和灵活,每个团队对领域驱动设计的理解不尽相同。这导致缺乏统一的标准和规范,使得开发者很难在实际项目中应用领域驱动设计。此外,由于缺乏标准,也很难评估和比较不同团队和个人的领域驱动设计实践水平,从而限制了领域驱动设计的普及和推广
由于领域驱动设计的缺乏标准,因此业界有很多质疑声音,质疑领域驱动设计是否可以被真正落地
本末倒置
技术人员喜欢将精力放在战术而忽略了战略,喜欢讨论各类设计模式、框架,部分个体系统设计的相当不错,整个系统确是千疮百孔,而DDD更关键的是在于战略层面,而非战术层面,如果战略规划乱七八糟,纵然使用DDD也很难收到成效
过度关注技术使得系统的好坏完全依赖程序员的个人素质,而战略好的程序员都去搞管理了,没有时间和精力把控整个项目的细节,DDD难以落地的真正原因实在技术之外的
没有统一的技术框架
尽量领域驱动设计强调将业务领域的概念直接映射到软件系统中,但具体如何实现这种映射并没有明确指导和建议。这使得开发者需要在实践中自行选择和设计相应的技术框架来支持领域驱动设计的实施。然而,由于缺乏统一的技术框架,开发者通常需要花费大量时间和精力来研究和设计适合自己项目的框架,这增加了项目的复杂性和风险
许多技术框架号称实现了领域驱动设计,然而这些框架实在是太难上手了。本来领域驱动设计的学习难度就够高了,这些技术框架又增加了学习成本,导致初学者望而却步
领域驱动设计不是一种技术架构,其实现与技术无关,任何面向对象的语言都可以用来实现领域驱动设计。这些技术框架只是其开发者自己的实践总结,未必适合所有团队和所有业务
哪怕不使用任何一种领域驱动设计框架,也可以完整实现领域驱动设计
门槛高
即便DDD的战术部分对于开发人员的要求也很高,数据库设计,代码规范,设计模式,全局业务的理解,系统优化策略等都是需要掌握的
过去数据驱动编程,只需要考虑数据库优化,代码优化等,现在转向DDD需要考虑模型设计,以及模型间的关系,如果优雅实现等,增加了很大的难度并且对于程序员的要求提高了很多
并且DDD需要统一语言,一般需要头脑风暴,而实际国内程序员内卷这么严重,每天一堆程序员开会讨论,基本上就被上层pass了
晦涩
DDD的一些概念比较晦涩难懂,比如限界上下文,领域等,这些都是对业务抽象在抽象得到的,很难理解,并且从代码上很难来体现,因为这些战略概念他是一种指导思想,具体到了实施层面,可能有各种不同的实现方案,所以如果不理解这些概念,从代码层面反推这些概念很容易被各家之言弄得头昏脑胀
无案例参考
比如微服务,你可以找到大量的落地方案,对于DDD有价值的参考非常少,大部分的案例都脱离了实际的业务,离开领域谈设计也不能说没意义,现实中计划使用DDD的业务场景可能非常复杂,一个小细节都可能阻碍工作的进展
过度吹嘘
分文章和书籍过分的夸大某些战术架构的优势而忽略了其缺点,甚至对于DDD本身也做了夸大,造成开发与运维成本的成倍增长及至于系统无法快速扩容甚于不得不重写
营销绑架
互联网行业喜欢制造概念,把简单的东西搞得很复杂,让认听上去很高大上,比如中台、低代码、DDD,这样的系统据有很高的营销价值,但是落地非常困难,尤其是在资源方面无法与理论对齐的时候,销售拉项目时通常会竖立各种Flag,可只要项目一到手就由不得客户了
不适合快速上线的系统
正确的建模从方案讨论、设计、实践、落地往往需要花费一段时间,面对业务紧急的需求以及倒排的工期,可能满足不了上线的要求。而其他一般架构不需要这些时间,短期投入成本高,但是从长期看,领域模型收益还是很高的
12.面向对象与DDD
针对于软件开发的部分我们往往会使用传统的面向对象分析设计但是它有一些问题,这也是DDD诞生的原因之一
OOAD是一种分析设计方案与DDD类似,不过在面对大型系统的时候有问题,OOP是面向对象指的是语言的那种比如C++,Java的面向对象语言,DDD依赖OOP
13.DDD的沉寂与爆火
沉寂
爆火
14.应用DDD
单体与DDD
对于单体系统而言,所有DDD组件都位于同一个应用程序中,但我们仍然可以从逻辑上对限界上下文进行拆分。这样各个限界上下文就是一个个模块
如下图所示,在单体系统中DDD的应用有几个显著的特点。首先,单体系统的数据库通常只有一个,所以资源库的实现相对简单,不需要考虑分布式环境下的数据一致性问题。然后,因为所有的代码都运行在同一个服务器实例中,所以诸如领域事件的实现过程也就不需要考虑跨JVM的消息通信机制
微服务与DDD
在微服务中服务的拆分粒度与边界始终是一个问题,而DDD虽然诞生的早但是以前都不火爆,在微服务大火的那几年大家发现DDD比较适合用来划分服务拆分粒度和划分服务边界,所以DDD也开始重新的火热
在基于DDD实现微服务架构时,我们可以按照限界上下文的粒度来确定微服务的大小。下图展示了限界上下文与微服务之间的对应关系
中台与DDD
中台这一概念来源于阿里的中台战略,目的是构建符合数字时代的、更具创新性和灵活性的大中台+小前台的业务组织方式。中台通常分成业务中台和数据中台两大类别,这里讨论的是业务中台
中台和微服务架构并不是同一层面的事物,可以简单认为微服务是构建中台的一种组件化实现手段。在中台架构中,每一个中台都由一组微服务构成。因此,我们可以在微服务架构的基础上添加对中台架构的描述,如下图所示:
15.DDD开发流程