区分DDD中的Domain, Subdomain, Bounded Context, Problem/Solution Space
译自: Domain, Subdomain, Bounded Context, Problem/Solution Space in DDD: Clearly Defined
领域驱动设设计是一种设计系统的方式,强调在领域专家和系统建造者之间创建一个通用的语言。著名的DDD原则包括:使用通用语言和确定隐性和显性。
DDD中的有些概念并没有明确的定义,且高度隐晦。每个人对域(Domain), 子域(Subdomain), 问题空间(Problem Space)和解决空间(Solution space)都有不同的理解。本文将会对这些概念进行澄清。
本文基于GitHub上的一个会话,参与会话的很多人都来自DDD社区。
模糊但没有歧义
在开始定义术语之前,我想强调Kenny Baas-Schwegler 提出的一个重要观点。他强调DDD应该是模糊的。由于DDD的模糊性,我们可以用它来探索、建模和解决新问题(现有的DDD模式和准则并没有限制我们的思维方式)。
模糊性意味着可以用一个词来描述在某些方面相似但并不相同的不同事物。例如"few",在一些场景下,它表示的范围可能是2-3,而在其他场景下可能表示不同的范围, 如5-10。关于模糊性最主要的是可以通过上下文进行推断(如果不同的人以截然不同的方式解释它,那就太模棱两可了)。
如果我说出一个词,期望对方能给出相同的定义,但对方实际上理解的是另一种定义,则说明没有对齐定义(即我们认为正在讨论同一件事,但实际上并不是)。
使用DDD时,我们希望拥抱模糊性,但同时也希望对每个概念的模糊程度有共同的理解。
以下的定义都比较模糊,但当我们使用这些词时,能够对齐对它们的认知。
Domains
DDD对领域的定义与剑桥字典中的定义非常类似:
上面对领域的定义非常模糊。什么是一个感兴趣的领域?有可能是任何事情。一个领域实际上是围绕某些概念的子集的任意边界。
How to group these concepts into domains?
如果使用彩色形状来表示概念,那么应该如何对它们进行领域划分?如你所想,实际存在很多划分的方式。
我们可以把方形放到方形领域,那圆形放到圆形领域。但蓝色方形和蓝色圆形也可以归属为蓝色领域。
The same concepts can belong to different domains
当对系统进行建模时,我们可以选择最合适的领域边界来使得软件和组织边界保持一致。即使我们选择按照颜色来对齐领域,但形状领域仍然存在。
在我参与的每个建模领域以及每个建模研讨中,不同的人都倾向于跨不同领域边界来分割系统。这是正常的,应该根据实际情况拥抱模糊性,并运用设计思维。
Subdomains
域和子域有什么区别?这个问题比较简单,子域并不是字典中的一个单词(domain存在于字典中,但subdomain不存在...)。子域在web世界中占有重要的位置,但在DDD中意味着什么?
在DDD中,一个子域是一个相对的概念。域和子域可以交互使用。当我们使用子域时,我们强调将该域作为另一个已经确定的更高级域的"孩子"。
因此,每个子域也是一个域,且大部分域都是子域。当我们的模型不包含更高级别的父域时,才不会将一个域认为是子域。
Core, Generic, Supporting (Sub)Domains
当听到一个核心域实际是一个子域时,很多人通常会感到困惑。在Eric Evans 的书中,他将领域称为核心域,但有时也会称之为子域。
你可以将域和子域认为是DDD中的模糊性之一,子域同时也是域,使用核心域还是子域并不重要,它们在概念上是模糊的,但并没有歧义。
核心域听起来更好,而核心子域则强调它属于一个更高级别的域。
Problem Space vs Solution Space: 更好的DDD模型
让人最困惑的是问题空间和解决空间。每个人对DDD上下文中的问题空间和解决空间都有不同的看法
我认为使用问题/解决空间模型太过简单,无法完整地传达DDD所要表达的内容,Simon Wardley的战略圆形则更加形象。
Simon Wardley’s Strategy Cycle
在上图中有如下元素:
- Purpose:我们关心的领域中存在哪些问题需要解决或需要达到什么目的?
- Landscape:我们关心的领域的当前状态是什么?
- Climate:领域的推动力是什么?我们该如何演进?
- Doctrine:我们应该普及的好的做法。
- Leadership:在现有和新领域中我们应该做出什么样的方案或变动。
Domains/Subdomains Problem 还是Solution Space?
除非我们可以明确定义问题或解决空间,否则无法对该问题做出回答。
当前的系统中包含(子)域,而(子)域中存在又会存在用户需求和相关问题。对这些需求和问题的解决会涉及多个(子)域,并会修改(包含子域的)系统状态。因此逻辑上所有的空间都会包含(子)域。
那么在决定为哪个子域设计解决方案时,是否存在仅存在于问题空间的子域?这样,一些域只需要与解决相关,而与问题无关。
从下图的例子中可以看到,是可以将一些子域作为单一的问题空间或解决空间,但没有必要这么做,应该采用更确切的方式对业务进行划分。
My understanding of problem and solution space in DDD. There are many other definitions out there.
新的解决方案也会带来新的问题,或正如Simon Wardley所说:高阶系统创造了新的价值来源。
我建议尽量避免使用问题空间,而应该准确地指出你所要表达的内容:purpose, landscape, climate, doctrine, leadership等。
无论何时,当用到术语"问题空间"和"解决空间"时,都需要阐明你所讲的观点。你的问题空间也是别人的解决空间,只是看的角度不同而已。
在作者的理解中,问题空间就是针对使用者来说,存在问题的地方;而解决空间就是针对提供解决方案的人来说,落地方案的地方。问题空间和解决空间只是不同人的不同视角而已。
领域是分层的
如果一个域可以包含子域,而子域又可以作为一个域,那么子域就可以包含更多细粒度的子域。域和子域是层级概念。
当设计社会技术系统时,通常我们会希望将域放到不同层级。一个组织的领导者可能会希望看到公司的7个顶级域。软件架构师可能会希望看到100个微服务的领域边界。
企业架构中会在不同层级用到业务能力的概念。业务能力可以看作是域或子域
Domains are hierarchical and they represent business capabilities
Subdomain vs Bounded Context
这是DDD中另一组可能让人混淆的概念,但如果明确了解了子域的定义,就非常容易解释。
我们已经得出,子域是一个非互斥的,任意概念的集合。而一个边界上下文是一个模型的边界,代表了模型的概念,关系和规则。相同的子域可能由无数模型构成。
DDD中的模型的表达方式多种多样,如便签或代码,以及任何展示领域概念,关系和规则的事物。
由于一个边界上下文是一个模型的边界,它可能包含来自多个子域的概念(如跨多领域的规则),或者可以将单个子域建模为多个边界上下文(如子域中的各个逻辑处理单元)。
Subdomains vs Bounded Contexts: Areas of the domain vs boundaries of models of the domain