- 實現領域驅動設計
- (美)沃恩·弗農
- 2535字
- 2020-09-05 00:22:01
戰略設計為什么重要
到現在,你已經學習了DDD的一些術語及其含義,但是我還沒有怎么講到為什么它們如此重要。我確實認為它們是重要的,同時,我也希望你在這一點上相信我。接下來,我會對此做出解釋。讓我們來看看SaaSOvation公司的項目進展情況,他們遇到麻煩啦。

在開始采用DDD的時候,協作項目組便開始偏離正確的軌道了,原因在于他們并不了解戰略設計,甚至連戰略設計的基礎都不了解。就像多數開發者一樣,他們將關注點放在了實體(5)和值對象(6)上,從而缺少一種更廣闊的視野。他們將不同的核心概念雜揉在一起,導致他們將兩個模型創建成了一個。不久之后,他們便感到痛苦了,如圖2.3所示。他們還沒有完全達到實施DDD的目標。

圖2.3 團隊不了解基本的戰略設計,這導致在協作模型中產生了不相匹配的概念。虛線之內表示問題所在。
團隊中有些人指出:“是不是因為用戶(User)和權限(Permission)與協作概念存在著緊密的耦合?我們應該跟蹤誰做了什么事情。”這時,一個高級開發者指出:“問題不單單在于耦合,到最后,論壇、討論、日歷和日歷條目都會在一定程度上與協作人員發生耦合,這是事實。問題出在我們使用的語言。”他進一步指出,問題在于論壇和討論等概念與錯誤的語言概念耦合起來了。用戶和權限與協作活動沒有任何關系,并且與協作的通用語言也風牛馬不相及。用戶和權限是與身份(Identity)和訪問(Access)相關的概念,即是與安全(Security)相關的。在協作上下文(Collaboration Context)中出現的每一種概念都必須與協作存在語言層面上的關聯,而現在它們沒有。“我們應該關注的是協作概念,比如作者(Author)和主持者(Moderator),這些才是協作活動中的正確概念和語言。”
如何命名限界上下文
你注意到了這里使用的“協作上下文”一詞嗎?在本書中我們將以這種方式來命名限界上下文,即“模型名+上下文”。這里的“協作上下文”表明它是包含有協作領域對象的限界上下文。同時,我們還有身份與訪問上下文(Identity and Access Context)和敏捷項目管理上下文(Agile Project Management Context)。
重申一遍,SaaSOvation的開發者在一開始并沒有意識到用戶和權限是與協作工具無關的概念。誠然,他們的軟件中是有用戶的,但是我們應該將不同的用戶種類區別對待,因為在不同的上下文中他們所完成的任務是不一樣的。在協作工具中,我們更關注的是用戶的角色,而不是他們是誰或者他們的權限如何。然而,在當前這個例子中,SaaSOvation的開發人員將協作模型與用戶和權限完全揉合在一起了,如果系統對用戶或權限的處理方式有所修改,這也將導致對協作模型的修改。事實上,這正是他們所遇到的問題——開發團隊決定從權限管理方式切換成基于角色的訪問管理方式。在決定切換時,他們才意識到這個由錯誤的戰略建模所帶來的問題。
開發人員現在明白了,論壇和“誰可以發表帖子,還有在什么條件下可以發表”其實沒有多大關系。論壇只需要知道“有作者正在發表帖子,或者有作者曾經發表過帖子”就可以了。于是團隊成員學到了:決定誰可以做什么事情其實是由另外一個完全不同的模型來負責的,在協作模型中,我們只需要知道這樣的問題已經被回答過就行了。在論壇中,我們關注的是:一個作者發起一次討論。這里的“論壇”和“作者”便是通用語言中的兩個清楚概念,使用該通用語言的協作模型便是協作上下文。用戶和權限,或者其他相似的概念,比如角色,應該屬于完全不同的上下文,并且需要和協作上下文分離。
開發團隊可以輕易地得出結論:此時需要做的只是將用戶和權限帶來的緊耦合去除就可以了。畢竟,將用戶和權限分離到另外的模塊并沒有什么錯誤的地方。這可以幫助團隊將這些概念放到同一個限界上下文的另外一個子域中——一個邏輯上的安全子域。然而,最好的方式是將用戶和權限放在支撐子域或者通用子域中,因為另外的核心域也可能會用到相似的功能。
因此,這種周全的考慮可以幫助他們避免更多潛在的問題。他們先前的做法還很有可能導致大泥球(Big Ball of Mud,3)架構。這里的問題并不僅僅是由于用戶和權限沒有得到適當的模塊化。雖然模塊化是一種重要的DDD建模工具,但是它并沒有解決語言上的問題。
讓這個高級開發者擔心的是,項目當前的情形很有可能導致一種散漫的思維模式。當團隊面對協作模型之外的一套概念時,核心域將變得越來越模糊。結果,他們得到的只是一個并不能反映協作通用語言的隱式模型。團隊真正需要理解的是他們正在開發的領域、子域和限界上下文,他們需要戰略建模的思維模式。
別啊,怎么又是“設計”這個詞!
你可以認為“設計”在敏捷中是個丑陋的詞匯,但是這種看法卻不適用于DDD。在敏捷中使用DDD是很自然的一種做法。我們需要將設計敏捷化,而設計不見得就一定是笨重的。
好了,到這里,SaaSOvation的團隊成員學到了不少。他們展開了很多研討,最后知道了處理領域和子域的重要性,我們將在后續章節中學到他們是如何做到這一點的。
向DDD社區看齊
本書的SaaOvation例子提供了3個限界上下文。這些限界上下文可能和你自己領域存在不同。這些例子展示的是非常典型的建模場景。然而,并不是所有人都同意將用戶和權限從核心域中分離。可能在有些時候將它們放在核心域里面是有道理的。和通常一樣,這只是一個團隊自己的選擇。但是,據我自己的經驗,這是那些DDD新手們經常會遇到的問題之一,結果他們把實現搞得一團糟。另一種常見的錯誤是,將協作模型和敏捷項目管理模型混為一談。這些只是常見問題中的一小部分,另外的建模錯誤我們將在其他章節中講到。
這些常見的建模錯誤是由于團隊缺乏對通用語言和限界上下文的理解造成的。因此,即便你并不同意SaaSOvation例子中那些特殊問題,這些問題及其解決方法對于所有的DDD項目都是適用的,因為他們都關注于某個特定限界上下文中的通用語言。
我的目標是通過最簡單的例子講解實現DDD的基本原則。如果這些例子妨礙到了我的教授和讀者的學習,那我是負擔不起的。如果我講到:身份及訪問管理、協作和敏捷項目管理都有自己的語言,那么讀者便可以從這些例子的著重點中獲益。每個團隊都可以自己選擇如何去發現適合自己領域的語言,并傳達領域專家的思維模型。這里我們假定,SaaSOvation開發團隊最終得出的結論是正確的。
關于子域和限界上下文,我所有的指導建議都和DDD社區緊密地保持一致。其他的DDD領導者可能有不同的關注點。然而,我所講的是適用于任何團隊的DDD基礎。澄清對于DDD的一些模糊認識是我的主要目標,而你的目標則是將本書中的DDD指導建議切實地應用在自己的項目中。