什麼是最小知識原則 (LKP)?
最小知識原則 (Least Knowledge Principle),又稱為 迪米特法則 (Law of Demeter, LoD),是軟體工程中一項旨在降低模組間耦合度的設計準則。其核心思想是:一個物件應該對其他物件有最少的了解。在實務中,這意謂著一個單元應該只與其「直接的朋友」交談,而不應跨越層級去挖掘「朋友的朋友」的內部細節(如避免 a.b.c.d() 的長鏈式調用)。透過限制物件間的知識範圍,開發者能建立起強大的封裝邊界,確保當某個模組內部實作變更時,不會引發連鎖性的系統崩潰,從而大幅提升軟體的穩定性、可測試性與長期維護性。
假設住在一個家庭中,家中有不同的成員,每個人都有自己的物品需要收納,例如衣物、書籍、玩具等。如果家中的每位成員都知道其他成員物品的詳細位置,甚至可以隨意修改,最終系統會變得混亂無比。
這種情況就好比在軟體架構設計中,模組之間過度了解彼此的內部實作,導致系統變得脆弱且難以維護。
什麼是最小知識原則 (Least Knowledge Principle)?
最小知識原則 (Least Knowledge Principle),在軟體工程領域中又被稱為迪米特法則 (Law of Demeter)。其核心思想是:一個物件或模組不應該了解太多關於其他物件的細節。每個單元應該只與自己「直接的朋友」交談,而不應該與「陌生單元」進行深入互動。
用去耦合的概念來看,物件間都應該保持「君子之交淡如水」的關係,不需要知道太多對方的相關情況。
職場哲學:離職原因的封裝
舉個同事離職的情況來說,人與人之間不需要講得太清楚。同事之間禮貌上交代離職原因,只需提到家庭因素或生涯發展即可,不需要詳細交代具體去向或真實的負面原因。因為在工作上過度理解其他「模組」(同事)的內部狀態,有時反而會影響團隊氛圍。
因為即使清楚知道同事真正的離職原因你也不一定會過得比較好,因為當發現離職同事表現很優秀但年度調薪只有 500 塊,整天跟老闆聊天喝下午茶的調薪 5000 塊,甚至同事交代離職原因也可能會影響團隊的工作氛圍,因為同事們離職後下一個工作年薪平均 +50%~100%,這個就是在工作上過度理解其他模組的壞處。
最小知識原則在工作上的實踐,就是將進度與專案細節完整記錄在文件中,讓其他同事能透過公開的介面(文件)獲取所需資訊,而不需深入挖掘對方的私人領域。這有助於降低人際與系統的耦合度,提升整體的可維護性。
識別違反原則的程式碼:鏈式調用的風險
在實務的程式碼重構中,最常見違反迪米特法則的例子就是「長鏈式調用」。
例如:player.getInventory().getWeapon().getDamage().calculate()。
這段程式碼讓 player 必須知道 Inventory 裡面有 Weapon,且 Weapon 有 Damage 屬性。這種「火車撞車」式的調用方式極其脆弱,一旦 Inventory 的結構改變,整串邏輯都會崩潰。遵循最小知識原則,我們應該將其封裝,改為 player.calculateAttackPower(),由物件內部自行處理細節。
程式碼實踐:封裝與抽象化
透過下方的範例,我們可以看到如何透過建立獨立的函式與介面,來落實最小知識原則:
- 玩家物件:封裝了自身的屬性和方法。
- 建立函式:
createPlayer只關心基本屬性,不干涉內部邏輯。 - 資料處理:
processPlayerData只調用公開的檢查方法,不需要知道特定物件的內部結構。
1 | // 定義檢查函式,專注於單一邏輯 |
在軟體開發中,每個模組只關心自己的內部實現,不隨意干涉其他模組。這不僅是技術上的去耦合,更是一種讓系統長治久安的設計智慧。不論是處理程式碼還是處理同事離職,保持適當的距離,才是最高境界。
FAQ:最小知識原則常見問題
Q1:鏈式調用一定是壞事嗎?那 Lodash 或 Promise 怎麼辦?
A:並非所有連點都是違反迪米特法則。 LoD 針對的是「跨物件獲取細節」。如果是 Lodash 這類對同一資料進行轉換(流暢介面 Fluent Interface),或者是 Promise 的鏈式非同步處理,並不違反原則。關鍵在於:您是否在透過朋友存取「朋友的私生活(細節)」?
Q2:遵循最小知識原則會不會導致過多的「中間轉發方法」?
A:有可能。 這是實踐 LoD 時常見的代價。為了不讓 A 知道 C,必須在 B 中建立許多代理方法。如果發現為了遵循 LoD 導致類別變得極其臃腫且充滿轉發邏輯,這可能暗示您的「層級劃分」或「責任歸屬」出了問題,需要重新檢視架構。
Q3:LoD 對前端元件設計有什麼具體啟發?
A:在 React 中,LoD 體現於 Context 的使用。與其傳遞一個包含整個全域 Store 的大物件讓子元件去慢慢「挖」它要的資料,不如透過 Selector 或特定的 Context 只暴露該元件所需的「最小資料集」。這能大幅減少元件因為無關資料異動而產生的副作用。
喜歡這篇文章,請幫忙拍拍手喔 🤣