域模型之二, 主要概念

简介:

这篇文章是一系列文章的第二篇。 如果还没有阅读过第一篇请从这里开始。 另在一月八日做了小改动, 增加了域语言(Ubiqitous Language)的定义。 

这篇描述可能比较枯燥的一篇。 不过这篇可能是大家最需要花时间理解的。 这些定义不是从某个文献上的摘抄,而是我根据自己的理解和我在阿里看到的一些建模中经常出现的问题, 而特别强调每个概念中经常被同学们忽略或者是误解的地方。   

这里先重复一下域模型的定义:域模型是为了准确定义需要解决问题而构造的抽象模型。 这个抽象模型中最核心的概念就是实体(Entity)。 

域(domain:前面提到了, 我们讨论的域是问题域。就是我们要解决问题的边界。 比如说电子商务领域, 就是任何通过某种电子媒介而使得买卖双方完成远程交易的过程中需要解决所有问题的汇总。

子域(subdomain:一个大的问题域又会被递归的分割为多个小的问题域。 比如说电子商务领域又会有和任何商品相关问题的商品域, 在这之下有商品发布的问题域, 也就是包涵任何与发布商品有关的速度,效率,准确性,流程,规则等等相关问题的总和。在商品发布的这一个子域之外,又会有一个相关的商品审核域, 用来解决任何和商品发布过程中和商品的知识产权,禁限售, 卖家的区域性授权等等相关的审核问题。  

语境(context:是一个特定人群在讨论的问题域是所形成的上下文。 这里要强调一个概念, 特定人群不是以团队或者是项目为边界划分的人群, 而是以知识为边界来划分的人群。 也就是说上下文不是普遍存在的, 而是存在于一个人群内部的,并且这些上下文大多是以隐形知识(Tacit Knowledge)的方式而存在的。  什么是隐形知识呢, 就是还没有被总结整理归纳沉淀的知识。 举例来说说AliExpress商品团队会有一个独立详情页和商铺详情页的概念, 这两个概念的准确定义和他们的商业目标的定义目前还没有显现化。 但是几乎团队内的每个人都能分别出这两个概念和他们所关联的问题。 这就是一个语境(Context)。

特定语境(Bounded context:是把上下文限定到某个特定的边界之内。 这个边界是由某个特定人群和他们所讨论的问题子域来决定的。 举例来从电子商务,到商品, 到商品发布, 到规则,到商品审核规则是从大到小的问题域,他们对应的特定语境就是越来越细分并且越来越准确的上下文, 而对应的人群也是越来越小并且越来越专业。  最常见的bounded Context就是某个国际标准组织, 他们会为自己的标准定义专业的名词, 语法, 和表达方式。 而一个大的标准,比如说Health Level 7 (HL7), 总共有数千的会员。 这些人又组成了更小的标准委员会。标准委员会内又有更小的讨论组。 这就形成的从大到小的分级。而另外一个医疗标准, DICOM,又形成了另外一个bounded context。

语境映射(Context Mapping:不同的语境之间会有交互, 那么从一个语境到另一个语境的翻译过程就是语境映射。 比如说刚才提到的HL7是一个医疗标准。 而DICOM是一个医疗图像标准。 每个语境有一套完整准确的定义。 那么当某个场景需要我们在两个语境之间做交互的时候, 我们就需要Context Mapping 了。 举个例子来说,一个普通咳嗽的病人可能会被医生推荐去做胸透, 那么信息就需要从一个只能理解HL7(医疗语境)的系统交换到DICOM(医疗图像语境)的系统。 那么在HL7系统中的模型就需要无损的映射到DICOM系统中去。 这就是个映射的例子。     

域语言(Ubiquitous  Language)是一个团队在某个特定语境之下建立的交流语言。 这个语言有两个要求:第一:特定语境。 这个语言不是自然语言, 而是在某个语境之内的一个特定语言。 任何一个团队或任何一名同学都可能横跨多个域,这些域内的各种概念可能不是显性化的,并且某些名词有可能会是重叠的。 比如说两位同学交流前端问题时在使用的域语言和这两位同学交流商家准入门槛时使用的域语言其实是两个域语言。 第二:准确无歧义。也就是在这个语境之下, 交流双方任何一个成员对某个名词,描述,上下文的理解和另一个成员的理解是一样的。 比如说“优质商品”这个词在我没有给出定义之前, 每个同学的理解都不一样。 但是在一个AliExpress灯具行业,这个定义就不存在歧义, 同学们甚至可以立即拉一个列表出来。 域语言这个概念是Eric Evans发明的。 可惜有点用词不当。 他给这个概念起名为 Ubiquitous Language。 而Ubiquitous 是无时无处不在的意思,也就是Omnipresent。 这与域语言的概念恰恰相反。 造成了大家理解上的困难。  个人认为应该叫“Domain Language”更合适。  

 

实体(Entity):是一个可以唯一标识的个体。实体到底是什么是一个哲学家争论了两千年的概念。我们不在此做更多的讨论。 但是在我们说讨论的计算领域里, 我个人认为有几个特性应该是普遍存在的。 第一, 实体可以是抽象也可以是客观存在的。举例子来说:一个人, 一个虚拟的角色,一个人群的画像, 一个人群的所认可的某个理论,都可能成为域模型中要讨论的实体。(说到这里, 我们传统的计算机领域对entity一词的翻译“实体”实质上不准确, 我觉得“个体”是更准确的用词)。 第二,我们讨论的任何个体是有其生命周期的。 它有个从不存在到存在,然后最终到不存在的过程。 首先说实体是有状态的。 并且往往实体在这些状态自己的转化是有实体之外的事件(Event)所触发的。 了解实体状态和触发事件其实是个认知一个实体非常关键的一环。这里的另一层含义是实体不是脱离个体而存在的运行规律。 用程序来打比方, 我们的实体不是计算逻辑, 而是被这些逻辑所操纵的对象。 从现实世界的角度来说, 实体可以是万物。 而主宰万物运行的自然规律“道”却不是实体。    第三,我们讨论的任何个体在我们的问题域之内是可以被单独的分辨出来的。这里我想强调一点,就是个体在一个特定的问题(子)域中可以被分辨, 而不是没有任何限定范围内的可以被分辨出来(Entity is Individually identifiable within the problem (sub)domain)。  举个例子, 在商品发布这个子域内, 我们可能有发布失败这个Event。 这个Event可能会有一个失败原因来描述。 失败原因的一种可能是”审核未通过”。 从发布这个角度来说,也许这就是我们对商品审核需要了解的最细粒度, 这里没有提到任何具体的实体。  然而在另外一个相关的商品审核域中, 我们需要描述具体是什么审核的动作导致了发布的失败。 审核域需要区分每个审核动作发生的时间, 内容,详细描述 等等, 也就是说每个审核动作在商品审核域中是一个独立存在的实体。        

事实上我看到最频繁的域模型设计纠结就发生在对实体的认知上。在解决一个问题的时候到底我们需要考虑什么实体经常是域模型设计最关键的一环。 后面我会介绍一下具体的设计思路。

触发事件(Domain Event是引起实体状态变化的事件。 触发事件客观存在, 有生命周期, 可以单独分辨,所以它本身也是一个实体。 但是触发事件并不一定需要被显性建模。 往往某些触发事件比如说用户注册,被当作实体外的运行规律的一部分。 但是我个人建议大家还是要描述触发事件,虽然不一定要在最终的Model Diagram里画出来。 

数值对象(Value Object简单来讲就是常数对象, 比如说一个数字, 一段文字, 某一组参数。这些常数可能递归的组成一个复杂的object。 但是从问题域的角度上来说, 这些常数不存在一个生命周期。  举个卖家系统的例子, 比如说我们需要解决商户注册的问题。 这个过程中我们可能发现如果我们为每个类目的商户设计一个模板, 就可以帮助用户提升注册速度了。 这个模板, 虽然很复杂, 但是从商户注册这个问题域来说, 它就是一个数值对象。 

数据对象可以是一个相对的概念。  在一个问题领域的数值对象可能是另一个问题领域的一个实体。 继续上面的例子,  随着我们商业拓展, 我们可能在很多国家建立很多市场, 每个市场可能很多类目, 甚至有些为这个市场定制的特定的类目, 而每个类目下我们会吸收很多的卖家。   在这种复杂商业环境下, 我们可能发现模板管理成了一个新的问题域。 在这个问题域下, 每个模板都能够被客观存在, 独立识别, 并且有生命周期, 所以模板成了问题域内的一个实体。 这其实就是大家最常见的领域建模过程中的纠结。   

实体类型(Entity Type:实体类型是某一类实体的聚类。 事实上我们很少把建模精力花在研究某个实体上,我们大多数时间在研究实体类型。 简单来说我们是在研究Class的定义,而不是研究某个object的定义。  这又是领域建模过程中又一个纠结点。 因为我们在谈论一个实体的时候, 我们是没有歧义的。 但是一旦抽象到类型,我们抽象的边界就是一个很大的问题。 举个例子,我们做电商都会有买家这个实体类型。 但是真正买家类型的定义我们很少深究过。但是仔细想一下, 1688, B2B, 天猫,淘宝,淘海外, 咸鱼, 猫超, 聚划算, AliExpress,每个阿里的电商子域的买家实质上大有不同。 这些买家类不是一个覆盖全电商领域的买家类型, 而是不同语境下不同的买家子类。 所以我们必须准确定义我们的问题边界, 在这种情形下是商业边界,才能准确的定义我们的实体类型。

关系(Relationship是实体类型(相当于Class), 而不是实体本身(相当于Object),之间的关系。 所以关系也会有属性, 也有实例。关系实例的特例有时候不能被关系类型所不能包涵的的情形。后面我们会提到具体的例子和应对方法。

场景(Scenario场景是问题域中的一个问题实例。 也就是说我们要解决的具体问题。 对Scenario的深度理解建议大家参考一下Scenario-Based Engineering的书籍。  Scenario生成是把一个抽象的问题转化成生动的实例。 举个例子,一键支付这个问题我们可以有两种方式表达, 一种表达是把一键支付这个事情抽象的描述成一个提升买家便捷性的流程。而另一种表达是把这个问题描述成发生在某个典型用户(Persona)的一个故事。 这个故事是这个典型用户在没有便捷支付的旧社会和有了便捷支付的新社会的两次不同经历。 这个故事有几个作用, 一是简化交流;二是锁定问题; 三是锁定目标用户,四是锁定核心价值。 这个故事不应该讨论竞争对手, 实现方式, 以及是否团队能力匹配。  事实上, 这是我们做领域建模需要首先花精力的地方。 一个建模的技术或者是产品的同学, 和一个做业务的同学, 或者是法务,服务,合作方, 卖家等等分别讨论不同的场景,达成共识, 最终从这些场景中抽象出我们的模型。

核心场景(Core Scenario是问题域中的不可以牺牲的问题实例。 牺牲场景,也就是不把某一类场景作为有必要解决的问题, 是一个既需要经验又需要Vision的难题。我们用户痛点到底在哪里,解决这些痛点是否对我们的未来有决定性意义。 举个例子:亚马逊的Jeff Bezos认定Mobile不是决定性的, 未来Device是决定性的。 所以有些Mobile shopping场景就不被认为是核心场景。而某些尚未成熟的device shopping场景反倒被认为是核心场景。 这就是一个商业判断。 当然这个判断正确与否还有待时间证实。我们做技术的一般不需要做出这样的判断, 但是我们必须清晰的了解这样的判断。 只有这样我们才能和业务团队保持同样的目标。

以上就是我总结的一些常见概念。 其他还有一些概念我们在用到的时候再介绍。  

这是一系列文章的第二篇。 第三篇在此。 

目录
相关文章
|
6月前
|
算法
数据结构域算法系列之二 贪婪算法和人生规划
数据结构域算法系列之二 贪婪算法和人生规划
42 0
|
8月前
|
数据库
主题域、概念、逻辑、物理四种模型有什么区别与联系?
主题域、概念、逻辑、物理四种模型有什么区别与联系?
|
3月前
|
算法 图计算
什么是图计算?请简要解释其概念和特点。
什么是图计算?请简要解释其概念和特点。
43 0
|
6月前
|
定位技术
定义系统、模型、结构等概念|认知建模笔记翻译(4)
定义系统、模型、结构等概念|认知建模笔记翻译(4)
50 0
|
11月前
图的定义与术语的详细总结
理解图的基本概念 各种图的定义 图的顶点与边的关系 连通图的介绍
59 0
|
存储 负载均衡 数据处理
一、计算机网络的概念、功能、组成和分类
一、计算机网络的概念、功能、组成和分类
一、计算机网络的概念、功能、组成和分类
|
存储 算法 安全
区块链包含术语概念【27术语整理汇总】
区块链包含术语概念【27术语整理汇总】
136 0
关于图和实例的学习之相关概念个人理解
关于图和实例的学习之相关概念个人理解
86 0
关于图和实例的学习之相关概念个人理解
|
设计模式 搜索推荐 领域建模
DDD领域驱动设计实战(一)-领域模型、子域、核心域、通用域和支撑域等基本概念
DDD领域驱动设计实战(一)-领域模型、子域、核心域、通用域和支撑域等基本概念
884 0

热门文章

最新文章