架構特性與權衡#
複雜度管理告訴我們架構是為了解決複雜度,但「複雜度」本身過於籠統。要把它落到可設計、可驗證的層面,需要一套更精確的語言:架構特性(Architecture Characteristics),也就是業界常說的「非功能需求」或「品質屬性(Quality Attributes)」。本章釐清這些名詞的差異,說明如何辨識真正該關注的特性,以及為什麼這些特性之間必然要取捨。
三個容易混淆的名詞#
| 名詞 | 觀點 | 說明 |
|---|---|---|
| 功能需求(Functional Requirement) | 業務/使用者 | 系統「做什麼」,例如「使用者可以下單」 |
| 非功能需求(Non-functional) | 反向定義 | 不是功能的需求,名稱消極,難以驅動設計 |
| 品質屬性(Quality Attribute) | 品保/驗收 | 對系統「品質」的衡量,例如可用性 99.95% |
| 架構特性(Architecture Characteristic) | 架構師 | 「會影響結構決策」的非功能面向,是架構師主動要設計的對象 |
這三者大量重疊,但「架構特性」這個說法最貼近架構師的工作:它強調的是那些一旦選定就會塑造系統結構的面向。並非所有非功能需求都是架構特性——有些可以靠後期調校解決,不影響結構。
把焦點從「非功能需求」轉成「架構特性」,是把消極的清單(「不要慢、不要當機」)翻譯成積極的設計目標(「為高吞吐而設計」),這樣才能驅動結構決策。
三判準:什麼才算架構特性#
一個面向要被列為架構特性,需同時滿足三個條件。任一不滿足,就不該佔用架構師的設計預算。
| 判準 | 問題 | 反例 |
|---|---|---|
| 非領域 | 它是否與具體業務功能無關? | 「支援信用卡付款」是功能,不是架構特性 |
| 影響結構 | 滿足它是否需要特定的結構設計? | 「按鈕要圓角」不影響結構,不是架構特性 |
| 對成功關鍵 | 它對系統成敗是否真的重要? | 過度設計常源於把「可有可無」誤當「關鍵」 |
第三個判準最常被忽略。架構師傾向把所有特性都拉到「重要」,導致過度設計。請參考簡單原則:能不列就不列,每多一個特性都會增加結構複雜度。
架構特性的三大分類#
把架構特性歸類,有助於在需求訪談時系統性地「掃描」,避免遺漏。
操作型(Operational)#
與系統運行時的行為有關,多半可量化、可監控。
| 特性 | 衡量問題 |
|---|---|
| 可用性(Availability) | 系統需要多高的正常運行時間? |
| 效能(Performance) | 回應延遲、吞吐量的目標為何? |
| 可恢復性(Recoverability) | 災難後多久要恢復(RTO/RPO)? |
| 可擴展性(Scalability) | 負載增加時系統如何成長? |
結構型(Structural)#
與程式碼的內部品質與組織方式有關,多半難以量化。
| 特性 | 衡量問題 |
|---|---|
| 可維護性(Maintainability) | 修改一個功能要動多少地方? |
| 可測試性(Testability) | 能否容易地撰寫自動化測試? |
| 可部署性(Deployability) | 發布一次的成本與風險有多大? |
| 可擴充性(Extensibility) | 加新功能是「插入」還是「動手術」? |
跨領域(Cross-cutting)#
橫跨整個系統、不易歸入前兩類,卻往往攸關存亡。
| 特性 | 衡量問題 |
|---|---|
| 安全性(Security) | 認證、授權、加密的需求為何? |
| 法規遵循(Compliance) | 是否受 GDPR、金融法規約束? |
| 隱私(Privacy) | 個資如何蒐集、保存、刪除? |
| 可用性/無障礙(Accessibility) | 是否需符合無障礙標準? |
隱式特性最易漏#
架構特性可分為**顯式(Explicit)與隱式(Implicit)**兩種:
- 顯式特性:寫在需求文件裡,業主明確提出(例如「尖峰每秒一萬筆交易」)。
- 隱式特性:沒人寫下來,卻被預設一定要有(例如安全性、資料一致性、合理的可用性)。
災難多半來自隱式特性。沒人會在需求裡寫「請不要洩漏使用者密碼」,但漏掉它後果嚴重。架構師的價值之一,正是主動把隱式特性挖出來、攤在桌面上討論。
挖掘隱式特性的提問清單:
- 這個產業有沒有監管或合規要求?
- 競品都具備、使用者預期一定有的非功能面向是什麼?
- 哪些「不出事就沒人提,一出事就上新聞」的面向(安全、隱私、資料完整)?
特性間必然取捨:不可全要#
架構特性之間存在相互拉扯,幾乎不可能同時最大化。試圖「全都要」會得到一個處處平庸的系統。
flowchart LR
P[效能] -.衝突.- S[可擴展性]
S -.衝突.- C[一致性]
SEC[安全性] -.拖慢.- P
SIMP[簡單性] -.犧牲.- EXT[可擴充性]
style P fill:#e3f2fd
style S fill:#e8f5e9
style C fill:#fff3e0
style SEC fill:#ffebee
style SIMP fill:#f3e5f5
style EXT fill:#ede7f6典型的取捨關係:
| 取捨對 | 拉扯關係 |
|---|---|
| 效能 ↔️ 安全性 | 每一層加密、驗章都增加延遲 |
| 可擴展性 ↔️ 一致性 | 分散式擴展常被迫放寬一致性(見分散式系統的 CAP) |
| 可擴充性 ↔️ 簡單性 | 為了「以後好擴充」而抽象,當下就變複雜 |
| 可用性 ↔️ 一致性 | 網路分割時,要嘛保可用、要嘛保一致 |
| 上市時間 ↔️ 任何品質特性 | 趕工幾乎一定犧牲某項架構特性 |
架構師的工作不是「達成所有特性」,而是在衝突的特性間做出明確、可被追溯的取捨。把取捨的理由記錄下來,正是 ADR 存在的理由。
設計時建議只挑出 3 ~ 7 個 真正關鍵的「驅動特性」,其餘列為「次要」,明確告知會被犧牲。
範例:把模糊需求翻譯成架構特性
業主原話:「我們要做一個很穩、很快、以後好加功能的電商後台。」
翻譯成可設計的架構特性與取捨:
| 業主說法 | 架構特性 | 量化目標 | 取捨決定 |
|---|---|---|---|
| 「很穩」 | 可用性 | 99.9%(年停機 8.8h) | 不追求 99.99%,避免異地多活成本 |
| 「很快」 | 效能 | P99 < 300ms | 接受最終一致以換取讀取效能 |
| 「好加功能」 | 可擴充性/可維護性 | 新功能不改核心 | 接受初期多一層抽象的複雜度 |
| (隱式) | 安全性 | 通過支付資安稽核 | 顯式列出,列為關鍵特性 |
關鍵:把「很穩、很快」這種無法驗收的形容詞,逼成可量測、可取捨的目標。
本章小結#
| 主題 | 核心觀點 |
|---|---|
| 名詞辨析 | 架構特性 = 會影響結構、攸關成敗的非功能面向 |
| 三判準 | 非領域、影響結構、對成功關鍵——三者缺一不可 |
| 三分類 | 操作型、結構型、跨領域,用於系統性掃描需求 |
| 隱式特性 | 沒寫下來的(安全、合規)最易漏,也最致命 |
| 必然取捨 | 特性彼此衝突,只挑 3 ~ 7 個關鍵,其餘明確犧牲 |
每次架構評審,先問三題:我們在優化哪些特性?我們明確放棄了哪些特性?這些取捨記錄在哪?答不出來,代表特性還沒被想清楚。