獨立性 (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)。透過網路封包通訊。完全隔離,最高程度的獨立性。網路延遲、分散式系統的複雜性高。

架構師的智慧: 好的架構不會在專案早期就鎖死在「微服務」模式(過度設計)。 好的架構允許你從單體開始,隨著系統成長,能夠平滑地將某些部分轉移到部署層級甚至服務層級。解耦模式是會隨時間改變的。