8.2.5.2 属性是否直接描述类
类和属性连在一起说"类的属性",应该能直接说得通,否则类和属性的搭配是不合适的。这个时候应该找到或建立合适的类,把该属性移进去。
例如图8-57,“人员的组织名称”是“人员的组织的名称”,人员→组织→名称,中间隔了个“组织”,"类的属性"不能直接说得通,需要添加一个“组织”类,把“名称”挪过去。

图8-57 属性要能直接描述类
“属性要直接描述类”这个要求和关系数据库的第三范式“不存在传递的函数依赖”相似。
对于每个属性,我们都这样思考:
“类”能决定“属性”吗?如果能,是怎么决定的?如果不能,还需要什么?
--这个人的姓名叫什么?
--潘加宇
--他为什么叫“潘加宇”?
--没啥理由,他就叫这个。
“姓名”作为“人员”的属性是合适的。
★如果进一步探究,这个人为什么叫“潘加宇”也是有理由的。
理由之一可能是:“潘”是家族的姓,“加”是字辈,这由家族的规则决定。“宇”则来自鲁迅的《无题》:心事浩茫连广宇,于无声处听惊雷。了解了这个规律,还可以进一步推导,“潘加宇”如果有个弟弟,那有可能叫“潘加雷”——但这些知识,不属于系统关注的范围,所以探究到此处就可以——“没啥理由”。
--如果知道专家是潘加宇,小时课酬能定吗?
--能,是1500元/小时。
--是怎么决定的?
--因为潘加宇的级别是“金牌专家”,公司规定“金牌专家”的课酬是1500元/小时。
决定的方式是:专家→专家级别→小时课酬。需要添加一个“专家级别”类,“小时课酬”作为它的属性。

图8-58 “类的属性”的调整
如图8-59左侧,我们可以问:
--如果知道商品是“百事可乐罐装330ml”,数量能定吗?
--不能。
--还需要什么?
--还需要知道是哪张订单。
因此需要一个类,既知道订单,又知道商品。添加“订单项”类,“数量”作为“订单项”的属性。

图8-59 “类的属性”的调整
属性如果放在了错误的类,极有可能会导致大量不同对象的某些属性值相同,而这反过来也可以作为线索:当发现大量不同对象有相同属性值时,可以检查一下,是否有属性放在了错误的类。
就以图8-57为例,如果按照左侧,可能会有如图8-60的一些对象,发现其中“人员”对象345677和345679的“组织名称”属性值相同,都是“腾讯科技(深圳)有限公司”。这时,可以检查一下,是否可能漏了一个“组织”类。

图8-60 一些人员对象
注意,以上是说“可以检查一下”,不一定就需要调整。多个对象的部分属性值相同的情况很常见,好多人姓名叫“张伟”,好多人年龄是18岁,并不一定要分出来另一个类。
可以合并的情况
如果A和B两个类存在1对1的关联,而且B只有一个属性,那么,可以把B合并进A,如图8-61。

图8-61 特定条件下合并类
图8-57提到的“人员”和“组织”并不符合合并的条件。即使“组织”只关注一个属性“名称”,也会出现图8-60的情况,因为可以有很多人员关联到一个组织。
符合合并条件的例子如图8-62的“人”和“出生”。一次“出生”事件只针对一个人,一个人只会出生一次,而且出生只关注一个属性:日期,那就可以把“出生”删掉,在“人”中放置“生日”属性。

图8-62 特定条件下合并类示例
如果一个人可以出生多次(带着前世记忆轮回,可能性趋近于0),或者出生除了时间之外,还要关注出生医院等其他属性(可能性较大),那就不宜合并了。
还可以看出,时间类型的属性实际上是某种事件发生的属性,只不过有的时候被合并到其他类中,看起来成为了该类的属性。如图8-62中,“生日”成为了“人”的属性,类似的还有:“下单时间”成为“订单”的属性等。
导致出现违反本要点的错误的原因有:
本文讨论了如何确保类和属性之间的合适性,强调属性应直接描述类,遵循关系数据库的第三范式,避免传递函数依赖。通过实例说明了如何调整类结构,合并或分离类,以及何时检查属性是否被错误地分配。

被折叠的 条评论
为什么被折叠?



