這章整合過去幾十年的系統架構智慧(如 Hexagonal Architecture, Onion Architecture, Screaming Architecture),提出了一個統一的「整潔架構」。
這些架構雖然細節不同,但目標一致:「關注點分離(Separation of Concerns)」。
一個整潔系統應具備以下特徵:
- 獨立於框架: 架構不依賴於特定程式庫
- 可測試: 業務規則可以沒有 UI、資料庫或 Web Server 仍被測試
- 獨立於 UI: 可以在不改變業務規則的情況下,將網頁換成 Console 介面
- 獨立於資料庫: 可以將 Oracle 換成 Mongo,業務規則不在乎資料如何儲存
- 獨立於外部代理: 業務規則對外面世界一無所知。
一、依賴規則 (The Dependency Rule)#
整潔架構由四層同心圓組成。要讓這架構運作,最重要的是:
「原始碼的依賴關係,須只指向內層。」
(Source code dependencies must point only inward, toward higher-level policies.)
- 內層圓圈中的任何東西,都不知道外層圓圈中的任何東西(包括類別、函數、變數名稱)
- 外層發生的變化,不應該影響到內層

Figure 22.1: The clean architecture
二、層級介紹 (由內而外)#
| 層級 | 顏色 | 內容 | 職責 | 特徵 |
|---|---|---|---|---|
| 實體層 (Entities) | 黃色 | 企業級的關鍵業務規則 | 封裝最通用的業務邏輯 | 最不受外部變化影響 |
| 使用案例層 (Use Cases) | 紅色 | 應用程式專屬的業務規則 | 編排與協調實體間的資料流 | 不該受 UI 或資料庫變更影響 |
| 介面轉接層 (Interface Adapters) | 綠色 | MVC 架構(Controllers, Presenters) | 資料轉換(內外格式轉換) | 知道 SQL,但內層完全不知道 |
| 框架與驅動層 (Frameworks and Drivers) | 藍色 | 細節(資料庫、Web 框架、UI) | 與外部世界溝通 | 只寫膠水程式碼來連接 |
flowchart TB
subgraph L4["框架與驅動層 (藍色)"]
DB[(資料庫)]
Web[Web 框架]
UI[UI]
end
subgraph L3["介面轉接層 (綠色)"]
Controller[Controllers]
Presenter[Presenters]
Gateway[Gateways]
end
subgraph L2["使用案例層 (紅色)"]
UseCase[Use Cases]
end
subgraph L1["實體層 (黃色)"]
Entity[Entities]
end
DB -.-> Gateway
Web -.-> Controller
Controller --> UseCase
Gateway --> UseCase
UseCase --> Entity
Presenter --> UseCase
style L1 fill:#fff3cd
style L2 fill:#f8d7da
style L3 fill:#d4edda
style L4 fill:#cce5ff三、跨越邊界 (Crossing Boundaries)#
當外層(Controller)想要呼叫內層(Use Case),或者內層(Use Case)想將結果傳給外層(Presenter)時,該怎麼辦?
1. 依賴反向 (DIP)#
根據依賴規則,依賴箭頭只能向內指。但控制流(Control Flow)常常需向外(例如:Use Case 呼叫 Presenter 顯示結果)。
- 解法: 在內層定義介面(Interface),讓外層去實作它
- 結果: 控制流向外,但原始碼依賴關係向內(Presenter 依賴 Use Case 的介面)

Figure 22.2: A typical scenario for a web-based Java system
2. 傳遞的資料#
- 原則: 跨越邊界時,傳遞資料應是簡單、獨立的資料結構(如 DTO, Data Transfer Objects)
- 禁忌: 千萬不要把「實體(Entity)」或「資料庫的一行(Database Row)」直接傳給外層(如 UI)。
這會導致內層定義洩漏到外層,或者迫使內層知道外層需求,破壞依賴規則
只要遵守「依賴關係向內」這鐵律,你就能輕易將系統分層,
並獲得一個可測試、可維護、易於更換技術細節的整潔架構。