在軟體開發中,總有一些部分特別難測試(例如 GUI 畫面、資料庫整合)。
為讓這些部分也能被納入測試覆蓋範圍,Uncle Bob 介紹了一個強大設計模式:謙卑物件模式(The Humble Object Pattern)。
一、謙卑物件模式#
這模式的核心思想: 將原本難測試的行為拆解成兩個模組(類別)。
- 謙卑模組 (The Humble Module):
- 包含所有難測試的行為(如直接操作 DOM、繪製像素)
- 邏輯非常簡單、甚至近乎愚蠢(Dumb),以至於不需測試(因為太簡單了,幾乎不可能寫錯)
- 因它什麼都不懂,所以很「謙卑」
- 邏輯模組 (The Logic Module):
- 包含所有與該行為相關的邏輯
- 完全不依賴 GUI 或 DB
- 易於測試
二、經典案例:Presenters 與 Views#
這是謙卑物件模式最常見的應用,發生在 UI 邊界上。
1. View (謙卑物件)#
- 角色: 它是 GUI 的外殼
- 職責: 只負責將數據載入螢幕。它不應做任何決策(例如:不該決定「因為餘額是負的所以顯示紅色」,只該負責「顯示紅色」)
- 測試: 難以測試,但因邏輯已被剝離,所以不需要測試
2. Presenter (邏輯模組)#
- 角色: 它是 View 的大腦
- 職責: 接受來自應用程式的資料,並將其格式化為 View 可直接使用的形式
- 將
Date物件轉換成字串"2023-10-27" - 將
Money物件轉換成字串"$100.00" - 決定布林旗標(如
isRedText = true)
- 將
- 測試: 非常容易測試,因它只是在操作單純的資料結構
3. View Model#
Presenter 與 View 間傳遞的是一個單純的資料結構,稱為 View Model。
- 它只包含字串、布林值和列舉(Enums)
- View 只是盲目地讀取 View Model 中的欄位並顯示出來
flowchart LR
subgraph 邏輯模組["邏輯模組 (易於測試)"]
P[Presenter]
end
subgraph 謙卑物件["謙卑物件 (難以測試)"]
V[View]
end
App[應用程式資料] --> P
P -->|格式化| VM[View Model<br/>字串/布林值]
VM --> V
V -->|顯示| Screen[螢幕]
style P fill: #d4edda, stroke: #155724
style V fill: #f8d7da, stroke: #721c24
style VM fill: #fff3cd, stroke: #856404三、其他應用:資料庫閘道器#
這模式不僅用於 UI,也用於資料庫邊界。
- SQL 是謙卑的: SQL 語句本身難以測試(需要連線 DB)
- Interactor 是邏輯的: 業務邏輯不該包含 SQL
- Gateway (謙卑物件): 介面轉接層中的 Gateway 負責執行 SQL。
這部分被視為謙卑物件,實作簡單的 CRUD,而複雜的查詢邏輯則盡量移至可測試的 Interactor 中
謙卑物件模式是「架構邊界」的守護者。 透過將難測試的「介面」與易測試的「邏輯」分離,我們能大幅提升系統的可測試性,
確保業務邏輯(Presenter/Interactor)即便在沒有 UI 或 DB 的情況下也能被完整驗證。