Ch14: 元件耦合性 (Component Coupling)
討論 Component 之間的關係 Outline:
- (ADP) The Acyclic Dependencies Principle
- (SDP) The Stable Dependencies Principle
- (SAP) The Stable Abstractions Principle
- Metrics: Management vs. random walks
- Components and Directory Structures
- Source code configuration system
(ADP) The Acyclic Dependencies Principle
Allow no cycles in the component dependency graph.
早上九點上班,努力測試,全過了,五點下班,隔天早上起來,Test 全壞了
解決方法:
Weekly Build 工程師星期一到四不管其他人,先幹了再說,星期五大家一起來解決 Integration 的問題 但是當專案長大到我們無法一天解決 Integration 的時候,開發週期只能一直變長, 開發者及 PM 的開發速度會一直下降
Eleminating Dependency Cycles 把開發環境區分成可釋出的元件 (releasable components), 每發布一個新版,依賴改元件的團隊 可以自行決定是否採用該版本,但是這個前提是絕不允許在結構中產生循環依賴,
See Figure 14.1 Typical component diagram
It is a directed acyclic graph (DAG).
需要發布系統時,可以由下而上進行編譯, 測試, 發布,圖中例子為 Entities,接著為 Database 跟 Interactors
Python 相依可視化工具 https://github.com/thebjorn/pydeps
循環依賴(Cycle)在元件依賴圖裡的影響
See Figure 14.2 A dependency cycle
發布及測試會變得非常麻煩
打破循環依賴
有兩個方法
- 使用依賴反轉原則(DIP),在圖14.3中,創建一個 User 類需要使用的接口,
class User:
def __init__(self, permission: Permission):
self.permission = permission
self.permission.auth()
class Permission:
def auth():
pass
class User:
def __init__(self, permission: IPermission):
self.permission = permission
self.permission.auth()
class IPermission(ABC):
@abstractmethod
def auth():
pass
class Permission(IPermission):
def auth():
pass
- 創建一個新 component,讓 Authorizer 跟 Entities 來依賴
See Figure 14.4 The new component that both Entities and Authorizer depend on
元件架構是隨時間演進的,他不會在一開始就設計好
(SDP) The Stable Dependencies Principle
Depend in the direction of stability.
- 一個 Component 應該只依賴比自己本身還要穩定的 Component
任何我們預期會經常變更的 Component 都不應該被一個難以修改的組件依賴,否則這個多變的組件也會變得難以被修改
個人感想: 就像 API 一樣,一但被別人用了,就很難再更改了
穩定性 (Stability)
See Figure 14.5 X: a stable component
See Figure 14.6 Y: a very unstable component
Stability metrics
Fan-in: 入向依賴 Fan-out: 出向依賴 I: 不穩定性(Instability): I = Fan-out / (Fan-in + Fan-out)
I 越小,代表被很多 Component 依賴 反之 則依賴其他 Component
See Figure 14.7 Our example
Calculate for for cc:
Fan-in = 3
Fan-out = 1
I = 1 / (3 + 1) = 1/4
在 C++ 這些依賴關係通過 #include 表達,同理 Python 用 import
並不是所有元件都應該是穩定的
See Figure 14.8 An ideal configuration for a system with three components
See Figure 14.9 SDP violation
See Figure 14.10 U within Stable uses C within Flexible
See Figure 14.11 C implements the interface class US
The Stable Abstrations Principle
A component should be as abstract as it is stable
越穩定的類別應含有越多的抽象類別
越不穩定的類別,抽象類別越少
Abstractness Metric
A = Na / N
Na = 抽象 class 的數量
N = 所有 class 的數量
主序列 The Main Sequence
Figure 14.12 The I/A graph
Figure 14.13 Zones of exclusion
痛苦區 The Zone of Pain
像 Database Schema,非常具體,每個人都依賴他,且非常難改 像 String, Integer,如果你不改,那就不需要抽象了,落在痛苦區也沒關係
沒用區 The Zone of Uselessness
通常發生在某個沒有人實現的抽象類別,他就躺在那
請避開痛苦區跟沒用區,盡量貼近於主序列區
Distance Metric
D = | A + I - 1 | 就是離主序列線的距離
結論:本章介紹各種用於依賴關係管理的指標,有些依賴好,有些不好