Skip to main content

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 全壞了

解決方法:

  1. Weekly Build 工程師星期一到四不管其他人,先幹了再說,星期五大家一起來解決 Integration 的問題 但是當專案長大到我們無法一天解決 Integration 的時候,開發週期只能一直變長, 開發者及 PM 的開發速度會一直下降

  2. 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

發布及測試會變得非常麻煩

打破循環依賴

有兩個方法

  1. 使用依賴反轉原則(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

  1. 創建一個新 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 | 就是離主序列線的距離

結論:本章介紹各種用於依賴關係管理的指標,有些依賴好,有些不好