# 耦合與系統設計 --- *Strong or loose, we live in dread,* *Of the coupling monster under the bed.* *Yet without it, your system would flake,* *Coupling is a pillar you can’t forsake.* --- ## 耦合是一切罪惡的根源? --- :「這邊的 code 一團亂,有複雜的相依關係。」 --- :「程式碼到底是誰寫的?」 --- git blame 下去,發現是半年前的自己... --- ## 一個完全沒有耦合的系統 --- ## 所有元件都彼此獨立、可替換 --- ## 寫起來很舒服 ## 想怎麼改就怎麼改 --- ## 但這是好設計嗎? ## 能滿足商業需求嗎? --- ## 什麼是耦合? --- ### 詞源 Coupling 源自拉丁文 *copulare*: > **co**:一起 > **apere**:連結、固定 意為「將事物連結在一起」。 --- 在生物學,copulare 則為「交配」的意思。 ``` ∧ _ ∧ ∧_∧ (,,´∀`,,)w< )ー♡ / ∩ づ C \ ``` --- ### 服務間存在耦合 = 服務間存在連結 --- #### 手錶內有無數的齒輪與彈簧相互連結 --- #### 引擎、車輪、剎車和其他零件耦合在一起成汽車 --- #### 不同的耦合設計,帶來不同的結果及維護成本 --- #### 我們根據什麼因素決定耦合的強與弱呢? --- ## 耦合程度 --- #### 耦合程度越大,它們需要同時修改的頻率就越高 --- ### 什麼原因導致這些元件需要一起改變? - 共享的生命週期 - 共享的知識 --- ## 共享的生命週期 --- ### A. 單體式應用程式 ``` ┌─────────────────────────────┐ │ Monolithic App │ │ │ │ ┌────────┐ ┌──────────┐ │ │ │ 付款 │───│ 授權 │ │ │ └────────┘ └──────────┘ │ │ │ │ 同一個部署單位 │ │ 同時啟動、同時關閉 │ └─────────────────────────────┘ ``` --- ### B. 獨立的模組 ``` ┌──────────────┐ ┌──────────────┐ │ 付款服務 │ │ 身份驗證服務 │ │ │ │ │ │ ┌────────┐ │ │ ┌──────────┐ │ │ │ 付款 │ │ ───> │ │ 授權 │ │ │ └────────┘ │ API │ └──────────┘ │ │ │ │ │ │ 獨立部署 │ │ 獨立部署 │ │ 獨立生命週期 │ │ 獨立生命週期 │ └──────────────┘ └──────────────┘ ``` --- ## 共享的知識 --- ### 元件為了能夠協同合作,必須共享知識 --- ### 共享知識可以用幾種不同的方式存在: - 知曉模組的介面 - 知悉對方的需求 - 獲知對方的實作細節 --- ### 在耦合元件的邊界,共享越多的知識, ### 你會遭遇的連鎖變動就越多。 --- ### A. 直接依賴具體實作 ``` ┌──────────────┐ │ UserService │ └──────┬───────┘ │ 依賴 ▼ ┌─────────────────────┐ │ <
> │ ├─────────────────────┤ │ BeginTransaction() │ │ ExecuteSQL() │ │ Commit() │ │ Rollback() │ └─────────────────────┘ ``` --- ### B. 依賴介面,但暴露實作細節 ``` ┌──────────────┐ │ UserService │ └──────┬───────┘ │ 依賴 ▼ ┌─────────────────────┐ │ <
> │ ├─────────────────────┤ │ BeginTransaction() │ │ ExecuteSQL() │ │ Commit() │ │ Rollback() │ └─────────────────────┘ ``` --- ### C. 依賴抽象介面 ``` ┌──────────────┐ │ UserService │ └──────┬───────┘ │ 依賴 ▼ ┌─────────────────────┐ │ <
> │ ├─────────────────────┤ │ Save() │ │ Query() │ └─────────────────────┘ ``` --- ## 知識的流動方向 --- ``` ┌───────┐ ┌───────┐ │ Sales │ │ CRM │ └───┬───┘ └───┬───┘ │ │ │ <---------------- │ 知識流動 (Knowledge Flow) │ │ │ ════════════════> │ 依賴方向 (Dependency) │ │ ``` --- ### Upstream and Downstream Component --- ### Upstream Component(上游元件) - 介面會公開**知識**,描述其功能及如何整合 - 知識的提供者 --- ### Downstream Component(下游元件) - 使用上游元件的功能 - 知識的接收者 --- ``` ┌───────┐ ┌───────┐ │ Sales │ │ CRM │ └───┬───┘ └───┬───┘ │ │ │ <---------------- │ 知識流動 (Knowledge Flow) │ │ │ ════════════════> │ 依賴方向 (Dependency) │ │ ``` --- ## 系統 > 《系統思考》:系統為一組相互連結的元素,其組織方式能夠達成某種目的。 --- ## 系統的三個核心要素 - 元件 (component) - 連結關係 (interconnection) - 目的 (purpose) --- ## 軟體階層 - 類別本身也能視為系統,其元件包含方法和變數 - 方法本身也是系統,由個別的程式描述來共同實現方法的目的 --- ## 系統中的耦合 --- ### 系統核心三元素 -
**目的**
需要**元件**和**連結關係** -
**元件**
和
**連結關係**
實現**目的** -
**元件**
允許**連結關係** -
**連結關係**
指揮**元件** --- ## 系統的改變 在任何系統中,你不可能只改變其中一個元素,但不影響到另外兩個。 這帶出了系統設計的重要概念: **邊界 (boundaries)** 。 --- ## 系統設計的本質 便是關於邊界的取捨。 (裡外有什麼、有哪些會跨過邊界或來回移動) --- ## 耦合 人們經常假設軟體設計要徹底去耦合,使元件完全獨立,但實際上並非如此。 若兩個元件要協作,它們就得**共享知識**。 --- ### 軟體工程師的工作 我們必須留意元件的連結關係,即元件間**分享了哪些知識**, 用**什麼方式**分享的,這些知識分享又會如何影響系統。 --- ## References - [軟體設計耦合的平衡之道](https://www.tenlong.com.tw/products/9786264141802) --- ʕ •ᴥ•ʔ: Thank you
返回文章