哪個類別該屬於哪個元件? 讓我們來看看元件的 內聚性
。
元件可以從一個 library 或是一個 micro service 角度去理解 (by yohuan)。
REP (Reuse/Release Equivalence Principle) 再使用性-發布等價原則
再使用性的細微度就是發布的細微度。
在過去十年裡,已經流行起模組管理工具,幫助我們建立大量可重用的元件以及元件庫。而透過可追蹤的發布程序以及相對應的版本編號,使我們可以重用軟體元件。
- 發布程序必須產生適當的通知以及文件
- 讓使用者可以決定何時以及是否要整合新版本
從架構的角度來看,組成一個元件的類別和模組必須是一個有內聚力的的群組。
- 組合到一個元件中的類別和模組應該被一起發布
- 共享著相同的版號、相同的版本文件
CCP (Common Closure Principle) 共同封閉原則
將那些會因著相同理由、在相同時間發生變化的類別收集到相同的元件之中。
如同 SRP 規定一個類別不應該包括多個引起變化的原因; CCP 也規定一個元件不應該包含多個引起變化的原因。
- 如果兩個類別不管在物理上或是概念上有綁定關係,總是一起變化,那他們應該屬於同一個元件。
大多數形況下,可維護性大過可重用性,如果一個應用程式需要更改,那我們希望更改都集中在單一的元件當中,而不是分散在各地。
- 僅需要重新部署更改的元件
- 剩下的不用重新驗證以及部署
如此一來,當需求來臨時,我們將變化盡可能的限制在最小數量的元件當中。
CRP (Common Reuse Principle) 共同重復使用原則
不要強迫元件的使用者依賴他們不需要的東西。
換句話說,要將傾向於一起使用的類別和模組放入同一元件當中
- Ex: 一個容器類別和其 iterator 應該放在同一元件當中。
如同 ISP 所言,我們不要依賴我們未使用的東西。
當一個元件使用另一個元件時,之間會建立一個依賴關係,也許只使用其中一個小類別,也無法消除這種依賴關係,每當依賴的元件發生變更時,使用的元件可能要
- 做出相對應的修改
- 或是重新編譯、驗證、部署
即使是我們沒使用到的小類別發生修改,我們依然無法避免。
這個原則除了告訴我們那些類別該放入相同元件裡,更告訴我們哪些類別 不要 放入相同元件裡。
內聚性的張力圖
上述三個內聚性原則像是在互相拉扯。
- REP 和 CCP 是 包容性 原則,傾向使元件變得更大。
- CRP 是個 排除性 原則,傾向使元件變得更小。
架構師必須要在這個張力圖當中,找到團隊當前該關注的位置,並隨時做改變。
- 通常專案的開始會在圖的右側,也就是會犧牲 重用性,隨著時間慢慢往左移動。
假設在開發串接shopee的元件
時
- Hard to reuse:
一開始會先考慮時程,而放棄版號控制,並把不同業務邏輯的類別放在一起加速開法,這會導致使用
元件
的開發者不能鎖定版號,如遇到破壞性變更,將導致服務不可用的情況發生。 - Too many unneeded releases:
因為發生多次不可用的情況,這時候加入版號控制,來因應需求的增長,因為未切割不同業務邏輯的類別,所以修改或增加一個類別就要增加版號,將導致多次不必要增加版號的發布。
- Too many components change:
專案趨向於穩定,也重新規劃
元件
,切割成多個不同業務邏輯的元件
,如 Auth Product Order...,但當Shopee更改Token驗證方式時,將導致對多個元件
做修改,增加開發時程。
Conclusion
過去,我們對於內聚性只認為 一個模組只能執行一個功能
,然而我們在選擇類別組成元件時,必須考慮到可重用性和可發展性的相對力量,並隨時保持動態平衡。