DDD领域驱动设计批评文集>>
《软件方法》强化自测题集>>
可到此处下载《软件方法》(下)目前公开的最新pdf版本:
http://www.umlchina.com/book/softmeth2.pdf
8.2.5.3 属性是否在本领域内可分解
如果属性再分解就得到另一个领域的概念,那么这个属性可以留在类中。如果属性可以继续分解成本领域的概念,那么可以考虑把这个属性独立出去变成另一个类。
如图8-83,"人员"的"称呼"属性的类型是String,相当于"人员"关联到String类。String属于基础语义领域,已经不属于"人员"所在的“人员管理”领域,那么"称呼"可以留在“人员”中作为属性存在。
图8-83 String可以留在类中
而"组织"还可以像右侧所示分解成“名称”、“办公地址”等,这些概念依然属于“人员管理”领域,所以可以考虑将“组织”分离为一个类,“人员”关联到“组织”。
图8-84 组织需要分离出来
注意以上的用词。我们只是说“再分解就得到另一个领域的概念”,并没有暗示这个另一个领域是什么,更没有暗示这个领域比核心域简单。任何领域,只要愿意深入研究,都是复杂的。
就拿“称呼”的类型String来说,String如果用.NET中的String类实现,这个类有157个操作,远远超过“人员管理”领域中某个类所拥有的操作数目。只不过String类如何构造是别人负责操心的事情,不是我们目标系统的建模人员操心的事情。
在分析工作流,我们只需要判断某个属性再分解就到了另一个领域,或者说类型是另一个领域的类。至于属性的类型具体是哪一个类,UML提供了一些原生类型,如果认为属性的类型刚好是这些类型之一,可以指定,否则可以先不指定,因为分析模型没有绑定到任何一个具体的编程语言和数据存储平台,而不同的编程语言和数据存储平台的类型体系还是有差别的。
在EA中,把类的语言设成none,在属性的类型选择中,就看到UML定义的原生类型,如图8-85。
图8-85 UML定义的原生类型
8.2.5.4 是否有多重性大于1的属性
如果某个属性经过了8.2.5.3 属性是否在本领域内可分解的检验,但该属性多重性大于1,即所谓多值属性。例如,人员有多个手机号。
这时可以:
(1)把“手机”属性留在“人员”类中,多重性设为多,如图8-86。
图8-86 把属性的多重性设为多
注意,只需要说明多重性为多,不要放上一个该属性的数组或List之类。人员有多个手机号,这是一个领域的知识;用编程语言如何实现多值属性,是另一个领域的知识。一旦混杂,又会导致批量刷工作量。
(2)更推荐的做法是,把该属性分离出去,如图8-87。
图8-87 分离多值属性
人员有多个手机号,背后往往是有原因的。虽然现在不关注,很可能以后就会关注。例如,有的手机号是私人用的,有的手机号是办公用的,如果需要关注这些知识,那么就需要从图8-87转成图8-88中的某一个,此时只需要添加关联或者在“手机”类添加一个属性。
图8-88 当需要关注更多的知识时,类图发生变化
当然,这也不是建模“人员有多个手机”的最好做法。后文我们介绍到人员相关的分析模式时,会详细描述如何建模这个领域。
以下做法是不好的:
(1)在“人员”类中放上多个属性“手机1”、“手机2”、“手机3”……,如图8-89。
图8-89 错误:放上多个属性
这样的做法相当于把抽象级别降到了对象级别,或者用关系数据库建模的说法,这是违反第一范式的。如果人员没有那么多手机号,某些属性就会出现空值;如果人员拥有手机号的数量大于预设的个数,就会放不下。
(2)只有一个“手机”属性,属性值里用逗号分隔各个电话号码。
如果这样的做法是好的,那不如更进一步。各个属性也不用分了,就一个字符串。还可以再进一步,类也不用分了,也串在一起……持久存储或网络传输时的序列化不就是这样干的吗?
根源就在于软件是人做的,人脑的容量和运行速度有限,否则就不用理得那么清楚了,直接对计算机下二进制指令不好吗?
8.2.5.5 属性是否对所有对象都有意义
如果通不过8.2.5.1 属性直接描述类的检验,那么类和属性放在一起是不合适的,但这只是必要条件,不是充分条件,即使通过了也未必合适。
如图8-90,人的姓名,人的▲▲(▲▲是男性特有的器官),人的〇〇(〇〇是女性特有的器官)好像都说得通,但如果问:是不是所有对象都应该有这个属性呢?得到的答案就不同了。
是不是有人有姓名——是。
是不是所有人都应该有姓名——是。
是不是有人有▲▲——是。
是不是所有人都应该有▲▲——不是,只有一部分人有。
是不是有人有〇〇——是。
是不是所有人都应该有〇〇——不是,只有一部分人有。
说明“人”发生了分裂,分裂成“男人”、“女人”两个子集(子类)。▲▲是男人的属性,〇〇是女人的属性。
图8-90 分解只属于部分对象的属性到子类
扫码或访问http://www.umlchina.com/book/quiz8_2_5.html完成在线测试,做到全对以获得答案。
1. [单选]以下符合“属性是否直接描述类”的是:
A)
B)
C)
D)
2. [多选]在符合某些条件时,这样建模是可以的,请把这些条件选上。
A) 开发团队决定走敏捷精益的领域驱动架构设计路线。
B) 手机只有一个摄像头。
C) 摄像头只关注一个属性:像素。
D) 用关系数据库来保存手机对象。
3. [单选]电子商务系统有一个类“商品”,“商品”有属性“名称”和“演示动画”。开发人员初步打算在实现时,“名称”的类型设为编程语言的String,“演示动画”的类型设为某个通用3D类库的“Animation”类。以下说法正确的是:
A 因为String比较简单,所以“名称”属性可以留在“商品”类内。
B 因为Animation比较复杂,所以“演示动画”属性应该分离出去变成关联。
C 因为String和Animation都比较复杂,所以两个属性都应该分离出去变成关联。
D 因为String和Animation都不属于核心域概念,所以两个属性都可以留在“商品”类内。
4. [单选]在某个系统中有一个“电子邮箱”类,它的对象用关系数据库存储,放在数据库的“电子邮箱”表中。“电子邮箱”表的部分行如下:
ID | 地址 | 用户名 | 密码 | SMTP | POP3 |
---|---|---|---|---|---|
11259 | zhangdaong@163.com | zhangdaong | alcohol150 | smtp.163.com | pop.163.com |
11260 | luodafeng@vip.sina.com | luodafeng | fengjie123 | smtp.vip.sina.com | pop3.vip.sina.com |
11261 | wanglihong@163.com | wanglihong | wipeshyn1 | smtp.163.com | pop.163.com |
…… |
作为一名学习了本部分内容的读者,看到这些行,应该想到的是:
A) 类和表的结构基本一致,类的属性相当于表的列。
B) 可能需要把“电子邮箱”的一些属性移到另一个类。
C) 密码不应该用明文存储。
D) 这样做不够敏捷,也不够DDD。
8.2.6 评价DDD话语中的“值对象”
在识别类的时候,有的建模人员受到DDD话语体系的影响,会着急去分辨哪个类是实体(Entity),哪个类是值对象(Value Object),这是没有必要的,而且很容易成为遮掩无能的遮羞布。
关于DDD话语中的“值对象”,可参见我写的《“值对象”是DDD的创新吗》一文,本书不再花大量篇幅阐述。
《“值对象”是DDD的创新吗》的要点:
(1)“值对象”类似概念不是Eric Evans发明的,也不是Eric Evans给起的名字。
(2)只需实事求是描述领域内涵,结果会自然而然显露出来,并不需要套上“实体”和“值对象”的概念。
(3)EricEvans以性能为理由来强调“值对象”的重要,不合适。
(4)“值对象”命名不严谨。
[202205升级知识讲解]23套UML EA和StarUML的建模示范视频-全程字幕
6月9-12晚网络软件需求设计方法学全程实例剖析公开课
5月26-29晚剔除“伪创新”的领域驱动设计-网络公开课
《软件方法》书中自测题-题目全文 分卷自测(1-8章)16套111题
《软件方法》强化自测题集110题
CTO也糊涂的常用术语:功能模块、业务架构、用户需求……[20210217更新]
如何选择UMLChina服务