架構決策概述#
做出架構決策是架構師最核心的職責之一。然而,許多架構師在做決策時會陷入反模式 (anti-patterns),導致決策不明確、不斷重複,甚至無法有效傳達。本章介紹三種常見的架構決策反模式、如何判斷一個決策是否具備架構意義 (architecturally significant),以及如何使用 Architecture Decision Records (ADRs) 來有效記錄架構決策。
Architecture Decision Anti-Patterns#
Covering Your Assets Anti-Pattern#
Covering Your Assets(自保型反模式)發生在架構師因為害怕做出錯誤決策,而不斷拖延或迴避做決策的情況。
典型表現:
- 架構師等待更多資訊才願意做出決定,即使已有足夠資訊
- 不斷推遲決策,直到時程壓力迫使倉促決定
- 在不確定時期傾向選擇「安全」選項而非最佳選項
解決方式:
- 在合理的時間範圍內大膽做出決策
- 持續與開發團隊合作以驗證決策的正確性
- 理解「不做決策」本身也是一個(通常更差的)決策
等到掌握所有資訊才做決策通常為時已晚。架構師應在擁有足夠資訊後盡快做出決策,並在後續透過迭代來調整。
Groundhog Day Anti-Pattern#
Groundhog Day(土撥鼠日反模式)指的是架構師做了決策,但因為沒有人理解為什麼做出這個決策,導致同樣的議題不斷被重複討論。
典型表現:
- 同一個架構議題在不同會議中反覆出現
- 團隊成員不斷質疑已經做出的決策
- 沒有人記得決策背後的脈絡和理由
解決方式:
- 提供決策的完整脈絡 (context) 和理由 (justification)
- 使用 ADRs 等正式文件記錄決策,確保所有利害關係人都能存取
- 明確溝通決策的技術和業務理由
Email-Driven Architecture Anti-Pattern#
Email-Driven Architecture(Email 驅動的架構反模式)指的是架構決策透過 email 進行討論和傳達,導致決策散落在無數的 email thread 中,難以追蹤和回溯。
典型問題:
- 重要的架構決策埋在冗長的 email 中
- 新進團隊成員無法找到過去的決策記錄
- 決策缺乏正式結構,難以理解其完整性
解決方式:
- 不要只透過 email 做出或公告架構決策
- 使用 ADRs 或類似的正式文件來記錄決策
- Email 可以用來通知利害關係人有新的決策,但決策本身應存放在可搜尋、可追蹤的系統中
Email 不適合作為架構決策的記錄系統。當有人問「我們為什麼選擇 REST 而不是 messaging?」時,你不會想要翻遍三個月前的 email thread 來找答案。
Architecturally Significant Decisions#
並非所有技術決策都是「架構決策」。Michael Nygard 定義了判斷決策是否具備架構意義的五個因素:
- Structure — 影響系統整體結構的模式或風格(例如選擇 microservices 還是 monolith)
- Nonfunctional characteristics — 影響架構特性(如 performance、scalability、availability)的決策
- Dependencies — 元件或服務之間的耦合關係
- Interfaces — 系統對外或元件之間如何存取和通訊
- Construction techniques — 影響開發平台、框架或工具選擇的決策
判斷一個決策是否具備架構意義的關鍵問題是:這個決策是否影響了系統的結構、非功能需求、依賴關係、介面或建構技術?如果答案為是,就應該正式記錄為架構決策。
Architecture Decision Records (ADRs)#
Architecture Decision Record (ADR) 是記錄架構決策最有效的方式之一。ADR 是一份簡短的文件,用結構化的方式捕捉一個架構決策的完整脈絡。
ADR 結構#
每個 ADR 包含以下五個基本部分:
Title#
簡短描述架構決策,通常以序號開頭。格式為:
- 短而清楚的敘述
- 包含足夠資訊讓人一眼理解決策主題
- 例如:「ADR 42: 使用 event-driven messaging 進行服務間通訊」
Status#
ADR 的當前狀態,通常有以下幾種:
- Proposed — 決策已提出,等待核准。適用於三種情況:(1) 需要更高層級的批准、(2) 需要架構委員會審核、(3) 需要更多資訊才能確定
- Accepted — 決策已被核准並準備實施
- Superseded — 決策已被後續的 ADR 取代,應註明取代它的新 ADR 編號
Context#
描述促使這個決策產生的情境,也就是「是什麼驅動了我們需要做這個決策」。Context 部分應保持客觀中立,描述系統面臨的現況和限制條件,而非偏向某個特定解法。
Decision#
正式記錄架構決策本身以及做出這個決策的完整理由 (justification)。這是 ADR 中最重要的部分。應清楚說明:
- 選擇了什麼方案
- 為什麼選擇這個方案而非其他方案
- 考慮過哪些替代方案(如果沒有單獨的 Alternatives 區段)
Justification 是 ADR 中最關鍵的元素。它直接解決了 Groundhog Day 反模式 — 當人們理解「為什麼」時,就不會反覆質疑同一個決策。
Consequences#
描述這個決策的影響和後果,包括正面和負面的。這部分記錄了決策帶來的 trade-off,有助於未來評估決策是否需要調整。
ADR 的使用方式#
- 將 ADRs 存放在版本控制系統(如 Git repository)或wiki 中,確保可搜尋和可追蹤
- 為每個 ADR 分配唯一的序號,便於交叉引用
- 當決策被取代時,不要刪除舊的 ADR,而是將其狀態改為 Superseded 並指向新的 ADR
- 定期回顧 ADRs,確保它們仍然反映當前的架構狀態
ADR 不需要很長 — 一到兩頁就足夠了。重點是捕捉決策的脈絡和理由,而不是寫一份詳盡的技術規格文件。好的 ADR 應該讓六個月後的新團隊成員能快速理解為什麼做了這個決策。