訊息專家三部曲(三) 總結篇 | Information Expert's Summary

What are you doing! Billy!,圖片來源
複習前篇
在前篇中展示了反面例子,以及如何按照了訊息專家的四步驟讓職責找到歸屬,並提及使用職責與實現職責的區別,在本篇中將會使用低表示差異與迪米特法則去支持資訊專家的論點。
但資訊專家也有他的極限,就像某個角色是最強的,但還是逃不過龍鱗、反發、成雙之流星一樣,在最後也會提及資訊專家的極限。
低表示差異、迪米特法則
一個好的概念或原則不會孤立的存在,而資訊專家作為分配職責的基本原則,當然是與許多設計原則相交呼應,但礙於個人的知識也有極限,覺得比較接近的就是以下兩個
- 低表示差異
- 迪米特法則
- 奧卡姆剃刀原則
低表示差異 | Low Representional Gap, LRG
“ 選擇反映領域詞彙的名稱可以,能夠增強且快速的理解,並且為程式碼區塊的預期功能提供線索。 ”
在最一開始情境描述的
- 這隻企鵝怎麼會飛啊 !
- 這個物件怎麼包山包海啊 !
- 這個專業術語怎麼跟網路上查的好不一樣 !
都可以不嚴謹的都可以歸因成軟體與認知、真實世界差異過大,而當差異過大,導致軟體是另一個世界,後續維護者要認識兩個世界,並且還要當其中的翻譯官。
低表示差異提倡,現實中的概念與關係要能實在地反映在軟體中,這樣有兩個好處
- 該系統貼近常識與認知。
- 就算沒有接觸過該軟體呈現的領域,但其中的概念與關係要 google 或查 ChatGPT 會十分方便。
資訊專家透過一套原則將職責分配給對應類別,或者說概念,使得不會開發時新增一堆純虛構的概念,同時,也讓概念與對應的行為有著緊密的聯繫。
在領域驅動設計中,更進一步要求開發者、客戶、業務在開發時針對某一概念的名稱一致,也就是統一語言 (Ubiquitouse language),更進一步減少溝通時的成本。
迪米特法則 | Law of Demeter
“ Only talk to your immediate friends ”
在反面例子,以及講解為什麼他是反面例子中,我們看到以下的程式碼
total += item.GetProduct().GetPrice() * item.GetQuantity();
這種 A 物件利用 B 物件去獲得 C 物件的操作,並且沒有領域概念的支援,將會拉大表示差異、提高系統的耦合度。
而迪米特原則 (Law of Demeter),也稱為最少知識原則 (The Least Knowledge Principle) 提倡物件 A 的方法 M 只能調用以下的方法
- 物件 A 本身的方法
- 作為該方法 M 入參物件 B 的方法
- 該方法 M 建立的物件 C 的方法
- 任何直接的物件的方法
迪米特原則也是封裝性的一種展現,通常會違反迪米特法則,都是物件暴露了太多自身的訊息,因此當一個物件全部都是 Getter、Setter,就要問自己以下的問題
這是物件導向設計嗎 ? 還是我只是用著物件導向的語言,然後寫著 DTO 跟方法拼湊而成的程式碼 ?
資訊專家將職責分配給擁有所需資訊的類別,極大程度避免 A 類別的屬性暴露給 B 類別去進行操作,可以說資訊專家自帶了迪米特原則的特性。
奧卡姆剃刀原則 | novacula Occami
“ 若無必要,勿增實體。 ”
奧卡姆剃刀原則為,通常對於某個現象或問題,會有各種的解決方案,而當中會有簡單的解決方案與複雜的解決方案,當兩者等效時,則選擇較為簡單的那一個。
用例分析後,我們可以採用不同的實現方法,在前篇中,我們看到兩種不一樣的解決方案,在其中反面例子相較於修改後的版本,要求我們多認識 OrderCalculator 這個類別。
而複雜會隨著元素的增加而同步遞增,除非你很清楚知道該用例在幹嘛,以及背起來解決方案,否則反面例子的複雜性永遠比修正後的要來的複雜,更何況反面例子的分配職責並沒有一個明顯的準則。
而資訊專家提供了一個簡明扼要的準則,即當一個類別擁有某職責的所有訊息,則分配職責到該類別,這會要求職責永遠分配在用例分析所揭示的元素,而不會另增一個實體(類別)去實作職責。
訊息專家的極限
“ 一切的確定皆是否定。 ”
資訊專家看起來就很完美了,將領域映射在軟體,怎麼還會有其他 8 個模式呢 ? 這就要來談設計與分析的差別了
設計與分析的不同在於,分析的目的是知道系統該做什麼,而設計的目的則是系統如何做到,前一個貼近問題領域,後一個更關注解決方法領域。
上面的論述太空虛了,來點實例,也就是完全按照資訊專家會有甚麼後果呢 ?- 職責的擴增 : 訂單具有所有訊息,所以將資料持久化的職責給他是正常的;現在需要驗證訂單,所以驗證的職責交給他是正常的。
- 職責的複雜度增加 : 隨著開發與依賴項的增加,訂單的結構複雜,導致建構子十分冗長。
- 屬性的擴增 : 因為持久化,所以將訂單更改時間、訂單創建時間等等,需要追蹤該筆資料非領域知識方面的資訊都加在訂單這個物件上。
因此只有資訊專家是不夠的,還需要低耦合、高內聚、純虛構、SOLID 等等模式加以制衡,制衡資訊專家的同時,也分解因為要落實在程式碼所以增加的複雜度。
作者心得
我非常喜歡要認識一個東西要知道他不是什麼,否定一個東西來確認他的邊界可以有效的避免胡亂使用。
這也是我認為直接接觸設計模式對一個開發者有害的原因,設計模式通常是為了解決一個複雜的交互、結構所提出的模式,但許多的複雜是人為的,有時候是因為沒有適當的分配職責造成的。