DDD领域驱动设计批评文集
做强化自测题获得“软件方法建模师”称号
《软件方法》各章合集
8.3 建模步骤C-2 识别类的关系
8.3.3 泛化的一些重点讨论
8.3.3.1 子集的不相交和完整
泛化是集合关系,在建模泛化关系时,我们对泛化关系中的子类(子集)的要求应该严格到什么程度?例如,不同子集可以有相同的元素吗?子集的并集必须等于全集吗?
UML规范对此持宽松的态度,泛化关系缺省是无约束的。如果要表达一个元素只能出现在一个子集中,需要给泛化关系加{disjoint}约束,如果要表达一个元素必须能出现在一个子集中,需要给泛化关系加{complete}约束,如图8-98。
图8-98 泛化的不相交和完整约束
(1)不相交
本书认为,同一个泛化集中的任意子类之间不相交,应该是缺省的做法。或者说,尽量把泛化建立在子类不相交的类之上。
例如,自然语言“员工有调度员、装卸工、配货员”,可能有的人画成图8-99的组合关联:
图8-99 错误的关联关系
这当然是错误的。“员工有调度员、装卸工、配货员”指的是“员工”的对象集合包含了“调度员”、“装卸工”、“配货员”的对象集合,不是指一个“员工”对象由“调度员”对象、“装卸工”对象、“配货员”对象组成。这个“有”是集合的“有”,是泛化关系,如图8-100。
图8-100 泛化关系
但图8-100也不是合适的建模结果,因为很可能允许员工身兼数职,同时既是调度员也是配货员。此时, “员工”的任意子集之间的交集不再为空,应该调整泛化结构所在的位置,例如改为图8-101。
图8-101 调整泛化关系的位置
图8-101中,“调度员”、“装卸工”、“配货员”的概念和图8-99相比含义已经不同,它们变成了“职位”的一种。“职位”的任意子集之间的交集应该为空。
如果“调度员”、“装卸工”、“配货员”取“职位”的概念,那么类似图8-99的图8-102其实也不是不可以。
图8-102 员工关联到具体职位
读者可以思考一下,如果把图8-102中的“员工”换成图8-79的“人”,下方的类换成“▲▲”和“〇〇”,可以吗?
如果对于不同职位,系统关注的差别在属性值上就可以体现,不需要在行为上体现,那么,图8-101的泛化关系可以取消,只保留“职位”,如图8-103。
图8-103 删去子类以及泛化关系
★图8-101到图8-103的“职位”,严格来说应该是“职位规格”。可以看得出来,“职位”实例的属性值不会随具体员工而变化。如果要记住张三做装卸工和配货员分别干了多少活,拿了多少绩效,还需要另外的类来区分。例如“员工-任职-职位”或“员工-职位-职位规格”。
(2)完整
本书认为,不需要要求子类完整,否则会导致批量刷废话。
如图8-104,一开始A有两个子类B和C,知道应该是不完整的。如果为了完整,强行加一个口袋子类“其他A”,那么很可能所有的泛化关系都会在结尾加一个“其他*”,这种批量的废话不如不要,缺省认为其不完整即可。
而且,“其他A”的集合元素是不定的,现在的含义是“非B非C”,假设以后A再加一个子类D,“其他A”的含义就变成“非B非C非D”,元素也变少了。
图8-104 不要求完整
当然,如果添加D为B或C更下一级的子类,是可以的。如果“其他A”经过时间的沉淀变成了一个领域术语,D作为“其他A”的子类也无妨——第6章所列的需求分类中的“非功能需求”就是这样的“其他A”的例子。