DDD领域驱动设计批评文集
做强化自测题获得“软件方法建模师”称号
《软件方法》各章合集
下图是《分析模式》原书第2章的图2.10,里面有一些错误和考虑不周的地方:
2004中译本和2020中译本的翻译如下:
基本上都是照搬,没有改过来。
Fowler网站上提供了该图的UML版本:
但从图上看,除了多重性和角色颠倒的错误得到修正——而且也没修正到位,角色应该靠近Party Type而不是放中间。
其他错误没有改过来,只是把这个图的表示法改成了UML。
我们下面先来看一下,图2.10有哪些问题,以及应该怎么改。
我把有问题的地方编了号,如下:
(1)
约束应该加在Accountability上,而不是加在Accountability Type上。
一般来说,**Type(**类型)这样的类,它的对象个数很少,而且值很稳定。很少需要在上面加不变式之类的约束。
就像一个类是“人”,一个类是“性别”,约束加在哪里?一般是加在“人”上面。
人的属性值会变,年龄增加,个子变高,体重变重,结婚有配偶……
他的属性值之间可能会存在约束。例如,如果年龄不到20岁,是不能有配偶的。或者说,如果说你年龄是20岁以下又有配偶,那就违反了约束。
如果在“性别”上搞一个不变式,“性别”除了“名称”,还有什么属性?让“性别”知道“人”然后把“性别”所关联的“人”(一个很大的集合)拉进来?那为什么不干脆放在“人”上面呢?
图2.10就是如此。约束加在Accountability Type上,但第1行就定义了一个x,说是self.Accountability,这不又绕回去了嘛,干吗不把约束加在Accountability上面呢?
(2)
假设我们咬紧牙关,坚持己见,一定要把约束加在Accountability Type上,但self.Accountability的Accountability在哪里呢?图上没有。
(3)
即使图上有Accountability,还有另一个问题:Accountability Type的self.Accountability是一个集合,不能直接.commissioner,得加类似->forAll(a|a.commissioner……
2020中译本把原文以复数形式表示的词都加了一个后缀“集合”,这个做法好不好另外讨论,不过如果这样做的话,下面这个地方也要加一个“集合”:
(4)
多重性和角色颠倒的问题:type、all types放在Party一侧,supertype和subtypes的多重性颠倒。
(5)
多了一个冗余关联all types,意思是Party所属的Party Type以及其上的所有supertype组成的Party Type集合。
在图上是用自然语言表达的,现在可以用OCL的闭包(Closure)运算来表达并删除冗余关联。
求闭包是关系代数常见试题,下图是2021年的一道软考题:
OCL有closure运算:
考虑以上的问题之后,我们修正的类图如下:
修改的要点:
(1)加上了“当责(Accountability)”。
(2)把约束放在“当责”上。
(3)多重性和角色位置的调整。
(4)删除冗余all types关联
(5)约束的意思是:
对“当责”的“委托方”(当事者)的“类型”(当事者类型)做求超类型的闭包运算,就得到了原书图上的冗余all types“当事者类型”集合,然后,该集合中有元素也在“当责”的“类型”(当责类型)的“委托方”(当事者类型)集合中,也就是说,这两个集合交集不为空。
对“责任方”也如此操作,就得到了图中的约束。