刁难我胖虎(修正)-《分析模式》漫谈45

DDD领域驱动设计批评文集

做强化自测题获得“软件方法建模师”称号

《软件方法》各章合集


“Analysis Patterns”的第4章“企业财务观察”有这么一小段:

Note how the hierarchies constraint on the parent association is necessary because the cardinalities alone do not enforce a hierarchy (although they might allow cycles).

2004(机械工业出版社)中译本的译文为: 

图片

2020(人民邮电出版社)中译本的译文为:  

图片

标红的although they might allow cycles,从原文来看,像2004中译本那样译为“尽管(虽然)允许形成环”是合适的,但从整句来看,此处并没有转折的意思,更像是解释原因——类似2020中译本的翻译。

所以,推断可能是原文没有选择好用词,导致了歧义。

这段话说的是原书图4.3,如下: 

图片

先把这个图的上的类型和关系转成UML类图: 

图片

Fowler还加了两个约束: 

图片

都是用自然语言描述的。我们来看为什么要加这两个约束,以及怎样改成更严谨的表达方式。

(1)multiple hierarchies,多个层级结构 

图片

如果把一棵树的信息用自反关联结构存放,确实是一个1对多的自反关联。

但是,1对多的自反关联,不一定就是一棵树。这也是文章一开始的文字的意思。

例如下面这个情况: 

图片

A、B、C形成一个环,B的父元素是A,C的父元素是B,A的父元素是C。(注:图中的箭头设为父指向子)。

上图的情况确实符合“维度元素”自反关联的多重性,但是它不是一棵树。

考虑到树有根结点(父为空的结点),多棵树有多个根结点,加一个约束“整个图至少有一个根结点”,足够得到树或森林吗?

也不一定,下面两种情况都满足这个约束,但一种是树,另一种不是: 

图片

图片

所以,这个约束只是必要条件,不是充分条件。

也就是说,不能通过约束每个维度元素的父结点、子结点的个数来保证维度元素组成的是树。换成数据结构的术语就是:只有顶点的入度和出度信息,没有办法判断是否有环。

可以像“有向无环图的约束怎么表达-《分析模式》漫谈39”一样,使用OCL的closure操作。针对每个结点,求它的超类型的“超类型”闭包所得的集合中不能包含它自己。 

图片

当然,仍然可能会出现下面的情形,但这也可以看作“多层级结构”。 

图片

(2)parent must be of same subtype

父(元素)必须是(本元素的)同一子类型。

首先,“子类型”这个“子”应该删掉。

这里说的子类型指的是“维度元素”的子类: 

图片

但“子类”只是一个类在某个泛化关系中扮演的角色,每个类都有可能是其他类的子类和超类。脱离开具体泛化关系指着一个类说“**子类”,是不合适的。

这个时候讨论的是“维度元素”的自反关联,已经不是在讨论“维度元素”和下面三个类的泛化关系,所以应该把“子”删掉。此处,Fowler应该是是受到了前面的惯性思维的影响。

为什么要说“父(元素)必须是(本元素的)同一类型”?

三个子类“地理维度元素”、“行业维度元素”和“产品维度元素”相当于“维度元素”的集合的三个子集,我们用不同颜色来标注: 

图片

如果组成树的话,同一棵树上的颜色应该是相同的,像下面这个是可以的: 

图片

原书中的图4.2就展示了这样三棵树: 

图片

(上图中的3个标记为“ACM”的结点,更合适的标记应该是“地理”、“行业”、“产品”。书中还推荐了一个没有领域含义的命名all,这个不是很合适。)

但下面这个就不可以。中间的树,红色的父元素是绿色: 

图片

所以这里要对“维度元素”加“父(元素)必须是(本元素的)同一类型”的约束。

但是Fowler在这里漏了一种可能,绿的父元素不一定是绿的,可以是空。

这个约束可以用OCL来表达,于是得到原书图4.3的完整UML改编如下: 

图片

左侧的约束意思是:

针对每一个维度元素,以下两种情况至少有一个为真:

*它的父为空

*父的类型就是它的类型 而且 对“父”求“父”的闭包得到的结果不包含自身

上一篇:2213445-35-1,BDP 630/650 X NHS ester呈固体或粉末状


下一篇:Java常用代码总结