识别实体与值对象的特征

简介: 识别实体与值对象的特征

甄别实体与值对象非常重要,正确与否会直接影响聚合的设计。


聚合是边界


在DDD中,聚合是实体与值对象的边界。一个聚合对外代表了一个完整的领域概念,遵循面向对象设计的基本原则,聚合内部往往由多个细小的高内聚领域概念组成。聚合内部的领域模型形成了一棵树,树的根必须是实体,可以称之为是聚合根(Aggregate Root),当然,也可以称之为根实体(Root Entity),它是聚合的唯一入口或出口。例如订单聚合定义了Order根实体,它就是订单聚合的唯一代言人。

在一个限界上下文的所有领域模型(实体和值对象)中,按照关系的强弱与概念的完整性,将其划分为多个聚合,就好像草原部落由一个个蒙古包构成了松散的聚居社群一般。

考虑到值对象与实体的差异,倘若需要管理它们的生命周期,则值对象不可能脱离聚合的边界单独存在。这就意味着,当我们要识别领域模型的聚合时,实体与值对象之间的强弱关系并不会影响到对聚合边界的界定。只要实体与值对象之间存在关系,无论关系强弱,该值对象都必须与存在关系的实体放在同一个聚合。如果一个值对象与多个实体之间存在关系,要么说明多个实体都属于一个聚合;要么意味着该值对象需要复制为多份,放到不同的聚合中,如下图所示:

image.png

如此一来,对于聚合边界的识别,就变成了对实体关系强弱的判断。只要我们正确地甄别了实体与值对象,在识别聚合时,就可以不再考虑值对象,如此就能降低识别的难度。


上下文的影响



虽然我们知道实体与值对象之间的本质差异在于是否具备唯一的身份标识(identity),然而许多时候,这一差异仍然显得似是而非。更何况,实体与值对象的定义并非绝对,在不同的上下文,同一个领域概念也可能定义为不同的设计类型。例如下图所示的钞票一枚:

网络异常,图片无法展示
|

购买上下文,买卖双方只关注钞票的面值与货币类型,只要值相等,即可认为是同一个对象,因而需定义为值对象;在印钞上下文,每张钞票都具有一个唯一的标识,即使同为100元的人民币,只要ID不同,也会认为是不同的对象,故而定义为实体。因此,要正确地甄别实体与值对象,需要结合具体的上下文。


识别的特征


即便如此,仍然缺乏相对客观的判断标准。为此,我总结了如下几个特征。


相等性


甄别实体与值对象,可以首先从相等性进行判断。只要一个领域模型对象的属性值相等,就认为是同一个对象,应优先考虑建模为值对象;否则,需要为领域模型对象定义唯一标识,并建模为实体。

注意:在进行相等性判断时,不能将作为唯一标识的ID视为领域模型的属性。

例如地址领域概念,只要其属性值国家、省份、城市、街道与邮政编码相等,就可以认为是同一个地址,应将Address类定义为值对象。对于大家耳熟能详的订单领域概念,显然需要为其分配一个唯一的订单编号,因为理论上可能存在除订单编号外其他属性都相同的两个不同订单,应将Order定义为实体。

然而,在对相等性进行判断时,可能出现ID与属性存在一种隐含的对应关系。例如,出版行业中作为正规出版物的图书,具有唯一的ISBN号,它相当于是图书领域概念的ID,所以Book应定义为实体。可在对Book相等性进行判断时,也可以不通过ISBN进行相等性判断,基本上,只要书名、作者(译者)、出版社、价格、出版日期、版次、页数、字数等属性值相同,也可以认为是同一本书,那是否意味着可以将Book定义为值对象呢?

显然,在进行相等性判断时,考虑的属性越多,就会出现多个组合的属性形成一种“隐藏”的唯一标识特征,有一些体现业务规则的ID,自身就是根据属性值来定义的。例如,航班的唯一标识就可以根据承运公司二字码、航班号、起降机场三字码与执飞日期来决定。通过唯一标识固然可以决定是否同一个航班,根据映射的多个属性值,也可以判断相等性。这会让人在甄别实体与值对象时,显得摇摆不定。例如,腾讯会议的会议号是Meeting的身份标识,在比较会议的相等性时,倘若我们考虑了除会议号之外的其他属性,如会议名称、会议类型、开始时间、结束时间、创建人、创建时间等属性,不一样可以确定会议的相等性吗?

因此,除了判断相等性,还需考虑不变性。


不变性


Eric Evans建议将值对象定义为不变的类,实则是因为根据值判等的值对象就应该具有不变性。仍以购买上下文的钞票为例,50元+50元=100元,这100元与原来的50元是另一张不同的钞票:

网络异常,图片无法展示
|

反之,一个对象除了ID,其余属性值都可以修改,不需要创建一个新的对象,就可以认为该领域对象是可变的,应考虑定义为实体。如前所述的Meeting对象,只要meetingId值不变,如会议名称、会议类型、开始时间、结束时间这样的属性值即使发生了天翻地覆的变化,我们也认为它是同一个会议。显然,应将Meeting定义为实体。

再考虑一个典型的订单聚合:

image.png


为什么我们要将订单聚合中的OrderItem定义为实体?如果不考虑ID属性,只要orderId、product与quantity值相同,完全可以认为是同一个订单项。然则,订单项的quantity值是可以更改的,更改了数量的订单项也不会认为是不同的订单项。订单项的可变性决定了它应该定义为实体。

为何要将OrderItem的Product属性定义为值对象呢?要知道,该Product类型还定义了productId属性,既然具有身份标识,不应该定义为实体吗?因为在订单上下文中,商品的productId来自于商品上下文的商品ID,在订单聚合中,可以将productId视为Product类的属性值。只要productId、name和price值相同,就可以认为是同一个商品,且它们的值是不变的。这正是将Product定义为值对象的原因所在。


独立性


即使考虑了相等性和不变性,仍有一种例外情形,那就是考虑独立性特征。值对象作为实体的属性必定附属于实体,不能单独存在;如果一个领域对象既满足了相等性,又满足了不变性,可定义为值对象;可是,如果它单独存在,且需要管理其生命周期,就需要将这样的类“升级”为实体。

考虑考勤上下文的假期领域概念。由于中国农历假期的缘故,每年都需要配置新的假期。假期概念对应的Holiday类定义为:

image.png

显然,该类的所有属性值相等,即可认为是同一个假期,一旦修改了假期的值,也可以认为是不同的假期,即Holiday类同时满足相等性和不变性,应定义为值对象。可是,在考勤上下文的领域模型中,Holiday类是完全独立的,不依附于其他任何实体,而它也需要管理生命周期。这时,就应遵循独立性特征,将其“升级”为实体。


优先级


以上三个特征并无重要性排列,需综合考虑。如果仍然无法判断,就遵循优先级原则:优先将领域概念建模为值对象。

相关文章
|
自然语言处理 数据处理
浅析命名实体识别(NER)的三种序列标注方法
简述序列标注 序列标注(Sequence Tagging)是NLP中最基础的任务,应用十分广泛,如分词、词性标注(POS tagging)、命名实体识别(Named Entity Recognition,NER)、关键词抽取、语义角色标注(Semantic Role Labeling)、槽位抽取(Slot Filling)等实质上都属于序列标注的范畴。
|
机器学习/深度学习 人工智能 自然语言处理
深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)
深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)
深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)
|
机器学习/深度学习 人工智能 自然语言处理
GraphIE:通过建模实例间和标签间依赖性联合抽取实体、关系和事件 论文解读
事件触发词检测、实体提及识别、事件论元抽取和关系抽取是信息抽取中的四个重要任务,它们被联合执行(联合信息抽取- JointIE),以避免错误传播并利用任务实例之间的依赖关系
198 1
|
人工智能 自然语言处理 Python
ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型
ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型
ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型
|
机器学习/深度学习 人工智能 自然语言处理
从零构建医疗领域知识图谱的KBQA问答系统:其中7类实体,约3.7万实体,21万实体关系。
从零构建医疗领域知识图谱的KBQA问答系统:其中7类实体,约3.7万实体,21万实体关系。
从零构建医疗领域知识图谱的KBQA问答系统:其中7类实体,约3.7万实体,21万实体关系。
|
存储 人工智能 JSON
基于TaskFlow法研杯 LAIC2022 【犯罪事实实体识别】
基于TaskFlow法研杯 LAIC2022 【犯罪事实实体识别】
415 0
基于TaskFlow法研杯 LAIC2022 【犯罪事实实体识别】
|
机器学习/深度学习 JSON 自然语言处理
[信息抽取]基于ERNIE3.0的多对多信息抽取算法:属性关系抽取
本项目讲解了基于ERNIE信息抽取技术,对属性和关系的抽取涉及多对多抽取,主要是使用可ERNIEKIT组件,整体效果非常不错,当然追求小样本学习的可以参考之前UIE项目或者去官网看看paddlenlp最新的更新,对训练和部署进行了提速。
|
机器学习/深度学习 自然语言处理 算法
实体,实体型,实体集,实体之间的联系
定义并解释概念模型中以下术语:实体,实体型,实体集,实体之间的联系。 (1)实体:客观存在并可以相互区分的事物叫实体。 (2)实体型:用实体名及其属性名集合来抽象和刻画同类实体称为实体型。 (3)实体集:同型实体的集合称为实体集。 (4)实体之间的联系:通常是指不同实体型的实体集之间的联系,实体之间的联系有一对一,一对多和多对多等多种类型。 ...
690 0
|
自然语言处理 算法 Linux
实体识别(2) -命名实体识别实践CRF
完整代码 https://www.heywhale.com/home/competition/6216f74572960d0017d5e691/content/
392 0
实体识别(2) -命名实体识别实践CRF