DDD战略设计相关核心概念的理解

前言

本文想再讨论一下关于领域、业务、业务模型、解决方案、BC、领域模型、微服务这些概念的含义和关系。初衷是我发现现在DDD领域建模以及解决方案落地过程中,常常对这些概念理解不清楚或者有歧义,导致我们不知道如何运用这些概念来落地我们的软件。

领域、业务、业务模型

  • 领域,即问题域、问题空间,领域是一种边界、范围。所以,一个领域代表了一个问题域的边界,也可以理解为是一个业务的边界。领域边界越大,业务范围就越大,反之则相反;通常我们大家交流都比较喜欢用业务这一词,比如这块业务,那块业务,业务的边界,我是一个业务开发人员(区分于我是一个中间件开发人员)。而领域一词,相对比较抽象,不是那么容易懂。

  • 领域既然是一个边界,所以可以划分领域的大小,即领域划分,划分出来的子领域简称子域,每个子域对应一个小的问题域和和小的业务;当然,不同的子域的重要性也是不同的,所以才有了核心子域、支撑子域的说法,这点显而易见。

  • 每个业务都有一个对应的业务模型(注意这个业务模型不是领域模型,而是一个业务概念的模型,领域模型下面会提到),这个业务模型设计的时候,完全不需要考虑任何软件设计的思想,比如对象的抽象、继承、存储、性能,等。我们是从业务本身出发,分析业务边界范围内的各种业务概念,以及业务概念之间的关系,通常我们可以使用一个业务模型的图来表达这些业务概念以及业务概念之间的关系。那么如何得到一个业务模型呢?最常见的有名词动词形容词分析法,还有比如四色原型分析法,都可以。找一个适合自己的就行;业务模型本身非常有价值,它提炼了领域内业务的核心概念及其关系,可以帮助我们更好的理解业务本身。

解决方案

  • 什么是解决方案?我们在进行DDD领域驱动设计的实践时,会进行需求分析、领域划分、领域建模等工作。而我们的系统要落地,则需要有一套解决方案。例如,我们要实现一个电商平台,需要一个复杂的系统解决方案,但是如果这个解决方案过大,各模块、组件都揉在一起,那么就不利于整个系统的维护、演进、伸缩,等。所以,我们需要把解决方案拆分为一个个独立的小的解决方案;所以,我们可以发现,领域和解决方案,是两个完全不同的概念,领域代表问题空间,解决方案代表解决方案空间。

  • 解决方案该如何拆分呢?简单的回答是:看情况,凭经验。说的具体点,就是我们需要使用软件设计的各种原则、最佳实践、设计模式、非功能特性的需求,以及团队成员的情况来指导我们进行解决方案的拆分或者直接不拆分,最终得出一个综合考虑后的拆分结果。所以,我们发现解决方案的拆分的维度可能有很多,没有一个单一的在任何情况下都合理的切分维度。有时我们可能从性能的角度来拆分,有时从不同架构分开演进(如CQRS架构)的角度,有时从分开伸缩的角度,有时从切合团队组织架构的维度。但是拆分的时候,多考虑一些各个因素,才能让我们更好的进行解决方案空间的拆分。

640?wx_fmt=jpeg

BC

  • BC,即Bounded Context,中文翻译为限界上下文。BC在DDD一书中首次出现,BC的理解分为两个层面:1)Bounded,表示边界的意思;2)Context,即上下文,我理解为是一个场景的上下文,这个场景不局限于普通的业务场景,而是各种上下文都涵盖在内,是一个时空感知的概念。比如我们两个人在公司交谈时的上下文是一个上下文,但是在路上交谈时,则切换到另一个上下文了,因为交谈的地点发生了变化;所以,BC合起来理解,就是一个上下文的边界。

  • BC有什么用呢?就是为了表达上面介绍的某个粒度的解决方案的上下文边界。那为何要强调这个边界呢?有了这个边界,我们才可以定义这个边界内的领域模型中所有对象概念的明确含义。如果没有这个上下文边界,对同一概念在不同上下文的理解,大家就会产生偏差。举个栗子:商品,在商品中心的解决方案BC中,商品中心负责管理电商平台的所有商品,所以商品在商品中心BC中,是一个聚合根;但是在订单中心解决方案BC中,虽然也叫商品,但是它只是一个值对象。我们知道订单中心的订单是一个聚合,订单内聚合了多条订单明细,每个明细是一个实体,每个订单明细对应了一个商品。虽然叫做商品,但是这个商品本质上只是商品中心的商品的一部分信息,如商品ID、标题、价格,且是只读的。甚至更为常见的,叫同一个名称的对象,在不同的BC中,是属性完全不一样的不同的对象。

  • 那为何解决方案的边界要叫做BC呢?对,我们可以不用叫做BC,比如你就叫做解决方案边界,也没问题。只是Eric在写作DDD这本书时,把他叫做BC,所以我们沿用了他的概念。我们主要的目的是为了用BC来表达解决方案空间的边界。

  • BC和子域的关系?没有关系。因为它们是不同的东西被划分后的产物,对解决方案空间进行划分产生了BC,对领域划分后产生了子域。而且它们划分的依据也不同,所以必定会出现BC与子域的关系是1对1,1对多,多对1的各种可能性。注意,我说的是被划分后的产物,所以这个产物叫什么其实不重要,我们真正要学会的是划分的原则、依据、经验,有了这些,我们才能合理地划分BC和子域。

领域模型

  • 什么是领域模型?这里讨论的领域模型是指DDD一书中提到的领域模型,领域模型是DDD软件设计方法论中的核心概念,它是业务分析、软件设计的综合结果,是一个系统设计模型。领域模型存在于某个粒度解决方案空间里。所以,任何一个领域模型,都是在特定的BC边界内才有意义;

  • 领域模型和业务模型的区别:我觉得领域模型有一个引起人们误会的地方,就是它的名称。很多人容易把领域模型理解为上面提到的业务模型,因为领域容易联系到业务,所以领域模型就是业务模型,比如非常著名的一本书《UML和模式应用》中,就认为领域模型是需求分析阶段的业务模型,是一种业务概念实体的模型。实际上两者是不同的,因为业务模型是对业务概念及其关系的表达,而领域模型在业务模型的基础上,用OOA/D的思想进行进一步精炼和抽象的对象关系模型,而且领域模型中有聚合、实体、值对象的区分。举亮个栗子:1)业务模型中,我们可能会有买家、卖家、读者、教师的业务概念,但是在领域模型中,我们已经把这些概念抽象为了账号这个模型。2)再比如一个读者持借书卡去图书馆借书这个场景,在业务模型中会存在一个借书卡的业务概念,而在领域模型中,我们很可能会去掉借书卡,因为它只是一个借书的工具,是借书系统用来识别读者的一个工具,系统真的的目的是为了知道哪个账号在借书,而不关心如何识别出这个账号。如果我们有一个网上借书系统,那就不需要借书卡了,而是要提供账号登录功能。在DDD一书中,作者一步到位直接根据需求设计出领域模型,在提炼需求分析需求的过程中直接应用软件设计思想和抽象思维一步到位产出领域模型,我个人觉得是有点快的,更好的做法应该是先分析出业务模型,再对业务模型进行精炼,得到领域模型;

  • 既然领域模型存在于某个粒度的解决方案空间中,而这个粒度的解决方案空间可能会对应多个子域。所以,这个领域模型则基于多个子域的业务模型结合起来推导出来的一个系统模型。同理,同一个子域内也可能有多个解决方案空间,既有多个BC,每个BC内有一个领域模型;

  • 那如何进行领域建模得到领域模型呢?这个就比较复杂了,不过经过前面的讨论,大致分为两个大的阶段:1)先得到业务模型;2)再对业务模型进行模型精炼;如何精炼?运用软件设计思想和原则,以及归纳演绎的抽象思维;所以,领域建模归根结底也是要“看情况,凭经验”,是不是很沮丧:)

微服务

最近几年,微服务开始流行起来,把DDD也带火了一把。那为何微服务的流行会让DDD也火起来呢?是因为微服务需要划分,而DDD中的BC的概念,大家发现正好可以和微服务的边界完全契合。比如都是对解决方案空间进行划分,都按照各种软件设计思想和原则进行划分,都提倡零共享。不过,DDD中实际上对BC的描述没有太多,尤其是如何得到BC这块没有展开。可能这块对大师来说是自然而然的事情,不需要过多介绍吧。

概念总结

  • 领域=问题域=问题空间=业务边界

  • 每个粒度的问题域都会推导出一个业务模型

  • 领域拆分、业务建模,是需求分析阶段该做的事情

  • 解决方案的边界即BC,解决方案可拆分

  • 每个粒度的解决方案都会推导出一个领域模型

  • 解决方案拆分、领域建模,是软件设计阶段该做的事情

  • BC边界即微服务边界,不同BC内的解决方案的架构可以是不同的,也即每个微服务的架构可以不同

原文地址:https://www.cnblogs.com/netfocus/p/DDD.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315651.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF1037H. Security

CF1037H. Security Solution 1 设原串为ststst。 对于单个询问,答案必然是询问串sss的一个前缀s[1..i]s[1..i]s[1..i]加上一个大于s[i1]s[i1]s[i1]的字符ccc构成。 因此我们只需要枚举前缀s[1..i]s[1..i]s[1..i],枚举字符ccc,快速询问s[1…

Visual Studio容器项目工程化心得

引言  关注博主的网友会看到我使用ASP.NET Core 容器化部署企业级项目的过程, 回想到开发过程中,鄙人有一些工程化心得, 分享给同学们。项目工程化因为本项目涉及单元测试Project、容器化部署、本地化的sqlite数据库,nlog日志&a…

CF1223F. Stack Exterminable Arrays

CF1223F. Stack Exterminable Arrays Solution 奇怪的套路增加了。 大概就是[l,r][l,r][l,r]能匹配完可以转化为[1,l−1][1,l-1][1,l−1]匹配后的状态和[1,r][1,r][1,r]匹配后的状态相同&#xff0c;因此hashhashhash判断即可。 Code #include <vector> #include &l…

从严治码-系统集成项目之根本

从4月份开始&#xff0c;由于备考《系统集成项目管理工程师》的原因&#xff0c;博客没有持续更新&#xff0c;在上半年考试结束之后&#xff0c;又对项目进行了一些收尾的工作。下面就这段时间的学习作一个记录和总结吧。在学习的过程中&#xff0c;提炼了一些自己认为比较重点…

CF924D. Contact ATC

CF924D. Contact ATC Solution 第一波转化挺妙的。 令tlitl_itli​表示用−w-w−w的风到原点的时间&#xff0c;tritr_itri​表示用www的风到圆点的时间。 显然(i,j)(i,j)(i,j)有解的条件为(tli−tlj)(tri−trj)<0(tl_i-tl_j)(tr_i-tr_j)<0(tli​−tlj​)(tri​−trj…

Insider Dev Tour 2019 | 以技术之力,展现传承魅力

世界原本是一个漆黑的山洞的大小&#xff0c;一个“胆大妄为”的人燃起火把&#xff1b;世界原本是一个孤岛的轮廓&#xff0c;一个“野心勃勃”的人扬帆起航&#xff1b;如今&#xff0c;世界的版图已经清晰&#xff0c;是什么让我们走出黑暗与闭塞&#xff0c;从未放下对未知…

免费馅饼 逆向dp

传送门 给你n个馅饼&#xff0c;之后给出n个馅饼掉落时间和位置。一共有11个位置从 0 ~ 10&#xff0c;这人初始在第5个位置&#xff0c;让后每一秒最多能移动一个单位&#xff0c;问这个人能最多能拿多少馅饼。 思路&#xff1a; 有点像数字三角形&#xff0c;但是需要逆着推…

CF840D. Destiny

CF840D. Destiny Solution 发现问题只有询问没有修改&#xff0c;且要维护类似众数的东西&#xff0c;瞟了一眼数据范围n,m≤3e5n,m\leq 3e5n,m≤3e5&#xff0c;果断莫队&#xff0c;一点不虚&#xff0c;写到一半发现删除不好直接维护&#xff0c;用setsetset会多一个loglo…

.NET 之 ORM 性能评测

Why你应该总能听到某ORM性能比Dapper高你应该有如下疑问&#xff1a;基准测试是否权威基准测试的方式是否合理基准测试的标准是否能够统一统一基准测试标准/规范如何进行姿势正确的性能测试相信大家对 Dapper 的性能&#xff0c;以及基准测试的权威性是没有疑问的&#xff08;否…

Loj #6089. 小 Y 的背包计数问题

Loj #6089. 小 Y 的背包计数问题 Solution 似乎是比较套路的东西。 我们发现对于i≤ni\leq \sqrt ni≤n​的部分是一个多重背包&#xff0c;而剩下的部分是一个完全背包&#xff0c;因此考虑分开计算之后合并答案。 part one 当i≤ni\leq \sqrt ni≤n​时&#xff0c;令fi…

CF817E Choosing The Commander 01tire 贪心

看到集合和异或&#xff0c;可以想到01tire(但是我没有想到)。 让后就可以对于每次插入和删除一个数&#xff0c;都在01tire树上操作即可。让后记录一下到当前位(当然是从高位到低位啦)有相同前缀的数的个数。例如样例建图出来大概是这样的&#xff1a; 可以看到从编号为2的点开…

不断进化的分支和需求管理

昨天有朋友在公众号私信问我几个关于代码分支管理的问题&#xff0c;这几个问题是我去年写的《在团队中使用GitLab中的Merge Request工作模式》一文结尾时抛出的几个问题&#xff1a;如果系统上线后有紧急Bug需要处理&#xff0c;这个流程应该怎样去调整&#xff1f;每个任务都…

Loj #6077. 「2017 山东一轮集训 Day7」逆序对

Loj #6077. 「2017 山东一轮集训 Day7」逆序对 Solution 令fi,jf_{i,j}fi,j​表示前iii个数产生jjj个逆序对的方案数&#xff0c;每次考虑把i1i1i1加入&#xff0c;有i1i1i1个插入位置分别产生0..i0..i0..i个新的逆序对。 因此fnf_{n}fn​的生成函数为(1x)(1xx2)…(1x…xn−…

CF56E Domino Principle 树状数组 + 简单dp

一个比较简单的题&#xff0c;但是我还是没做出来(哭。 很容易想到从后往前做&#xff0c;所以我们可以维护一个dp数组f&#xff0c;f(i)表示到第i个牌倒下能达到的最远距离。 f直接倒着跑&#xff0c;每次取[x,xh−1][x,xh-1][x,xh−1]的最大值即可&#xff0c;可以用线段树比…

基于Docker的Consul服务发现集群搭建

在去年的.NET Core微服务系列文章中&#xff0c;初步学习了一下Consul服务发现&#xff0c;总结了两篇文章。本次基于Docker部署的方式&#xff0c;以一个Demo示例来搭建一个Consul的示例集群&#xff0c;最后给出一个HA的架构示范&#xff0c;也会更加贴近于实际应用环境。一、…

Hills And Valleys CodeForces - 1467B 思维

给你一个数组&#xff0c;最多可以修改一个数&#xff0c;问最少的山峰和山谷数量之和。 小菜鸡做了一年。 一上来想猜个结论&#xff0c;让每个数等于其相邻的两个数&#xff0c;看了题解之后也证明的正确性&#xff0c;当时直接写就没后面这么多事了。 但是命运让我分情况讨…

2018 ACM-ICPC World Finals Problem D.Gem Island

2018 ACM-ICPC World Finals Problem D.Gem Island Solution 其实就是求x1x2⋯xnnd,xi∈[1,d1]x_1x_2\dots x_nnd,x_i\in[1,d1]x1​x2​⋯xn​nd,xi​∈[1,d1]的前rrr大的xix_ixi​的和的期望&#xff0c;可以发现每一种不同的序列{xi}\{x_i\}{xi​}的出现概率都是一个定值&a…

[译]使用LazZiya.ExpressLocalization开发多语言支持的ASP.NET Core 2.x项目

介绍开发多语言支持的ASP.NET Core 2.x Web应用程序需要大量的基础架构设置&#xff0c;并且耗费时间和精力。这篇文章&#xff0c;我们将使用LazZiya.ExpressLocalization nuget包一步本地化支持。背景大多数网络应用程序都是基于网址的本地化。因此我们可以在网址中看到所选的…

2019 ICPC World Finals Problem B. Beautiful Bridges

2019 ICPC World Finals Problem B. Beautiful Bridges Solution 太菜了&#xff0c;sbsbsb题调了一个下午。 首先有一个显然的O(n3)O(n^3)O(n3)的dpdpdp&#xff0c;令fif_ifi​表示最后一个桥柱在iii的最小代价&#xff0c;枚举上一个桥柱jjj&#xff0c;因为地面超过桥拱…

ac 梦幻布丁 启发式合并

题意&#xff1a;中文题。 对于每种颜色&#xff0c;我们都可以看成一个集合。让后把一种颜色变成另一种颜色就转换成了把两个集合的合并问题。显然我们有一个复杂度为O(NlogN)O(NlogN)O(NlogN)的启发式合并能完美的解决这个问题。 解决合并问题了&#xff0c;现在需要解决如何…