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“當事者類型”集合,然后,該集合中有元素也在“當責”的“類型”(當責類型)的“委托方”(當事者類型)集合中,也就是說,這兩個集合交集不為空。
對“責任方”也如此操作,就得到了圖中的約束。