整潔的架構 (The Clean Architecture)#

這一章整合了過去幾十年的系統架構智慧(如 Hexagonal Architecture, Onion Architecture, Screaming Architecture),提出了一個統一的「整潔架構」。 這些架構雖然細節不同,但目標一致:「關注點分離(Separation of Concerns)」

一個整潔的系統應具備以下特徵:

  1. 獨立於框架: 架構不依賴於特定程式庫。
  2. 可測試: 業務規則可以在沒有 UI、資料庫或 Web Server 的情況下被測試。
  3. 獨立於 UI: 可以在不改變業務規則的情況下,將網頁介面換成 Console 介面。
  4. 獨立於資料庫: 可以將 Oracle 換成 Mongo,業務規則不在乎資料如何儲存。
  5. 獨立於外部代理: 業務規則對外面的世界一無所知。

一、依賴規則 (The Dependency Rule)#

整潔架構由四層同心圓組成。要讓這個架構運作,最重要的一條規則是:

依賴規則: 「原始碼的依賴關係,必須只指向內層。」 (Source code dependencies must point only inward, toward higher-level policies.)

  • 內層圓圈中的任何東西,都不知道外層圓圈中的任何東西(包括類別、函數、變數名稱)。
  • 外層發生的變化,不應該影響到內層。

二、層級介紹 (由內而外)#

1. 實體層 (Entities) - 黃色#

  • 內容: 企業級的關鍵業務規則
  • 形式: 包含方法的物件(Object with methods)。
  • 特徵: 最通用、最高層級。除非業務模式本身改變,否則它最不受外部變化(如頁面導航改變、安全性升級)影響。

2. 使用案例層 (Use Cases) - 紅色#

  • 內容: 應用程式專屬的業務規則。
  • 職責: 編排與協調實體之間的資料流,以達成使用者的目的。
  • 特徵: 它不該影響實體,也不該受 UI 或資料庫變更的影響。

3. 介面轉接層 (Interface Adapters) - 綠色#

  • 內容: MVC 架構通常位於此層(Controllers, Presenters, Gateways)。
  • 職責: 資料轉換
    • 將資料從「適合使用案例和實體」的格式,轉換為「適合外部代理(如 DB 或 Web)」的格式。
    • 反之亦然。
  • 特徵: 這一層知道 SQL 是什麼,但內層(使用案例)完全不知道。

4. 框架與驅動層 (Frameworks and Drivers) - 藍色#

  • 內容: 所有的細節。資料庫、Web 框架、UI、外部設備。
  • 職責: 與外部世界溝通。
  • 特徵: 這是最外層,我們通常只寫一點點膠水程式碼(Glue code)來與之連接。

三、跨越邊界 (Crossing Boundaries)#

當外層(Controller)想要呼叫內層(Use Case),或者內層(Use Case)想要將結果傳給外層(Presenter)時,該怎麼辦?

1. 依賴反向 (DIP)#

根據依賴規則,依賴箭頭只能向內指。但控制流(Control Flow)常常需要向外(例如:Use Case 呼叫 Presenter 顯示結果)。

  • 解法: 在內層定義介面(Interface),讓外層去實作它。
  • 結果: 控制流向外,但原始碼依賴關係向內(Presenter 依賴 Use Case 的介面)。

2. 傳遞的資料#

  • 原則: 跨越邊界時,傳遞的資料應該是簡單、獨立的資料結構(如 DTO, Data Transfer Objects)。
  • 禁忌: 千萬不要把「實體(Entity)」或「資料庫的一行(Database Row)」直接傳給外層(如 UI)。這會導致內層的定義洩漏到外層,或者迫使內層知道外層的需求,破壞依賴規則。

總結: 只要遵守「依賴關係向內」這條鐵律,你就能輕易地將系統分層,並獲得一個可測試、可維護、易於更換技術細節的整潔架構。