獨立性 (Independence)#
一個好的架構必須同時支援系統的四大需求:使用案例、運行、開發、部署。 為了達成這個目標,架構師手中的核心武器就是**「解耦(Decoupling)」**。
一、架構支援的四大支柱#
1. 使用案例 (Use Cases)#
- 顯眼性: 架構必須讓使用案例成為「一等公民」。系統的意圖(Intent)應該在架構中清晰可見。
- 結構: 透過將特定行為化為顯眼的類別或模組,名稱應清楚描述功能(如
AddOrder,DeleteUser)。
2. 運行 (Operation)#
- 靈活性: 雖然硬體升級可以解決效能問題,但架構應保留將元件分離到不同伺服器運行的選項(如將高運算量的服務獨立出來)。
- 通訊: 元件間若保持適當距離且不預設通訊方式,未來面對運行需求的變化(如從單機變成分散式)會更容易。
3. 開發 (Development)#
- 康威定律 (Conway’s Law): 架構結構會反映組織結構。
- 隔離: 為了讓多個團隊能並行開發且互不干擾,系統應被分隔成完全隔離、可獨立開發的元件。
4. 部署 (Deployment)#
- 即時性: 目標是「熱交換(Hot-swap)」。
- 解耦: 如果元件與使用案例都良好解耦,新增功能只需加入新的 jar/dll,而不需重新編譯或部署整個系統。
二、解耦的策略:切蛋糕的藝術#
要實現上述的獨立性,我們必須在兩個維度上進行解耦:
1. 水平分層 (Horizontal Layers)#
這是最常見的分層方式,依照技術角色來切分:
- UI 層
- 應用程式特定業務規則
- 企業級業務規則
- 資料庫層
- 目的: UI 的變更不應影響業務邏輯;資料庫的更換不應影響 UI。
2. 垂直切分 (Vertical Slices)#
這是依照使用案例來切分。
- 概念: 每個使用案例(如「新增訂單」)都是一個垂直的切片,它貫穿了 UI、業務邏輯到資料庫。
- 目的: 透過將「新增訂單」與「刪除訂單」分開,新增一個使用案例時,不會干擾到舊有的案例。
三、重複的迷思 (The Myth of Duplication)#
工程師通常被教導要「消除重複(Don’t Repeat Yourself, DRY)」。但在架構層次,有些重複是好的。
- 真重複 (True Duplication): 兩段程式碼一模一樣,且總是為了相同的理由而改變。 $\rightarrow$ 必須消除。
- 假重複 / 意外重複 (False/Accidental Duplication): 兩段程式碼目前看起來一樣,但在未來會沿著相異的路徑發展,為了* *不同的理由**而改變。 $\rightarrow$ **必須保留**。
常見陷阱: 許多人喜歡將「資料庫的 Entity」直接拿來當作「UI 的 View Model」使用,因為它們欄位看起來一樣。 這是錯誤的。 UI 和資料庫會因為完全不同的理由改變。如果你把它們綁在一起,未來 UI 的改動就會意外影響資料庫層。 請容忍這種「假重複」,分開定義這兩個類別。
四、解耦的模式 (Decoupling Modes)#
我們可以在不同的層次上實現解耦,這取決於專案的規模與需求:
| 層級 | 描述 | 優點 | 缺點 |
|---|---|---|---|
| 原始碼層級 (Source Level) | 單體 (Monolithic)。所有元件在同一記憶體位址,透過函式呼叫通訊。 | 簡單、速度快。 | 依賴關係複雜,難以獨立部署。 |
| 部署層級 (Deployment Level) | DLL/JAR/Gem。透過動態連結通訊,但可獨立發佈。 | 可獨立部署,版本控管容易。 | 仍需在同一程序(Process)中運行。 |
| 服務層級 (Service Level) | 微服務 (Microservices)。透過網路封包通訊。 | 完全隔離,最高程度的獨立性。 | 網路延遲、分散式系統的複雜性高。 |
架構師的智慧: 好的架構不會在專案早期就鎖死在「微服務」模式(過度設計)。 好的架構允許你從單體開始,隨著系統成長,能夠平滑地將某些部分轉移到部署層級甚至服務層級。解耦模式是會隨時間改變的。