概述#

架構設計是將架構驅動因子(architectural drivers)——包括功能需求、品質屬性情境、限制和關切——轉化為架構結構的過程。本章介紹 Attribute-Driven Design (ADD) 方法,一種系統化、可重複的架構設計方法。ADD 的核心理念是:架構設計不是一次性的活動,而是透過多輪迭代(rounds and iterations)逐步精煉而成。

設計的結果——架構——將成為新成員教育、成本與時程估算、團隊組建、風險分析,以及最終實作的基礎。

Figure 20.1: Overview of the architecture design activity

建立系統背景#

在啟動架構設計之前,必須先確定系統的範圍(scope)——什麼在系統內部、什麼在系統外部,以及系統將與哪些外部實體互動。這個背景可以用系統背景圖(System Context Diagram)來表示。

Figure 20.2: Example of a system context diagram

Attribute-Driven Design (ADD)#

ADD 的架構設計以輪次(rounds)執行,每輪可包含一系列設計迭代(iterations)。一輪涵蓋在一個開發週期內執行的架構設計活動。透過一次或多次迭代,產出符合該輪設計目的的架構。

每次迭代中執行一系列設計步驟。ADD 對迭代內每一步提供了詳細指引。

Figure 20.3: Steps and artifacts of ADD

ADD 的七個步驟#

Step 1:審查輸入#

在開始設計輪次之前,需確保架構驅動因子(設計流程的輸入)已就緒且正確。這些輸入包括:

  • 設計目的(Design Purpose):明確本輪的目標,例如為早期估算產出設計、精煉現有設計以建構新增量、或設計原型以降低技術風險
  • 主要功能需求(Primary Functional Requirements):通常以 use cases 或 user stories 捕捉
  • 主要品質屬性情境(Primary QA Scenarios):應已由最重要的利害關係人優先排序(參見 Chapter 19 的技術)
  • 限制(Constraints):對設計選擇的硬性約束
  • 關切(Concerns):需要在設計中考慮的議題

架構設計如同軟體工程的大多數活動,是一個 garbage-in-garbage-out 的過程。如果輸入品質不佳,ADD 的結果也不會好。驅動因子真的在「驅動」設計,因此確保它們正確且優先順序正確至關重要。

這些驅動因子構成一個架構設計待辦清單(architectural design backlog)。當你對清單中所有項目都做出了設計決策,即完成本輪設計。

Step 2:選擇驅動因子以建立迭代目標#

每次設計迭代聚焦於達成特定目標,通常涉及滿足驅動因子的一個子集。例如,迭代目標可能是建立結構以滿足特定的效能情境或某個 use case。

Step 3:選擇要精煉的系統元素#

滿足驅動因子需要做出架構設計決策,這些決策體現在一個或多個架構結構中。精煉可以是:

  • 分解(Decomposition):自上而下,將元素分解為更細粒度的子元素
  • 組合(Combination):自下而上,將元素合併為更粗粒度的元素
  • 改進(Improvement):改進先前識別的元素

對於全新系統(greenfield),從建立系統背景開始,選擇唯一可用的元素——系統本身——進行分解。對於既有系統,需要對 as-built 架構有良好理解,可能涉及逆向工程或與開發者討論。

在某些情況下,Step 2 和 Step 3 的順序可能對調。例如,在設計全新系統的早期階段,可能先聚焦於系統的某個元素,再考慮要處理哪些驅動因子。

Step 4:選擇設計概念#

選擇設計概念可能是設計過程中最困難的決策,因為你需要:

  1. 識別各種可能用於達成迭代目標的設計概念
  2. 從這些替代方案中做出選擇

可用的設計概念類型包括:

  • Tactics(戰術)
  • Patterns(模式)
  • Reference Architectures(參考架構)
  • Externally Developed Components(外部開發的元件)

每種類型都可能有大量選項,需要仔細分析才能做出最終選擇。本章後續在 Section 20.3 會詳細討論。

Step 5:實例化元素、分配責任、定義介面#

選定設計概念後,需要決定如何從中實例化(instantiate)元素。例如,若選擇了 Layers 模式,你必須決定使用多少層、它們之間允許的關係——因為模式本身並未規定這些細節。

實例化之後,需要:

  • 分配責任:例如在三層架構中,展示層負責使用者互動、業務層管理應用邏輯與商業規則、資料層管理資料持久性與一致性
  • 建立元素間的關係:允許元素互相協作
  • 定義介面:介面是元素之間資訊流動的契約規格

Step 6:繪製視圖草圖並記錄設計決策#

到此步驟,迭代的設計活動已完成。但你可能尚未確保視圖(結構的表示)被保存下來。

  • 繪製草圖:可以是白板照片、繪圖工具的圖、甚至一張紙上的素描
  • 記錄設計決策與理由:包括重要的權衡決策,以便後續分析和理解

在 ADD 中我們說的是「草繪」(sketching)視圖,這是一種初步文件。正式的、完整的文件化(若需要)在設計迭代完成後才進行(見 Chapter 22)。

Step 7:分析當前設計並審查迭代目標的達成度#

確認本次迭代的部分設計確實解決了既定目標。建議讓另一個人協助審查——與程式碼審查的道理相同,不同的人有不同的假設、經驗基礎和觀點,有助於發現「bugs」。

完成分析後,應評估:

  • 是否已執行足夠的迭代來滿足本輪相關的驅動因子
  • 設計目的是否已達成,或是否需要在未來的專案增量中進行額外的設計輪次

是否需要繼續迭代?#

以風險作為指引。至少應處理最高優先的驅動因子。理想情況下,應確信關鍵驅動因子已被滿足,或至少設計「足夠好」能滿足它們。

深入 Step 4:設計概念的識別與選擇#

作為架構師,大多數時候不需要也不應該重新發明輪子。主要的設計活動是識別和選擇現有的設計概念來應對最重要的挑戰。設計仍然是原創且有創造力的工作,但創造力在於對這些現有解決方案的適當識別、組合和適配

識別設計概念#

識別可用的設計概念可能令人望而生畏,因為選項數量龐大且散布在各種來源。可以透過以下方式識別替代方案:

  • 利用既有最佳實踐:使用現有目錄(如模式目錄、框架文件)。優點是可以識別大量替代方案並借鏡他人經驗;缺點是搜尋和研究需要時間,資訊品質和作者偏見不明。
  • 利用自身知識與經驗:如果目前系統與過去設計的系統相似,可從過去的設計概念入手。優點是快速且有信心;缺點是可能反覆使用相同想法,即使有更好的新方法。
  • 利用他人的知識與經驗:透過與同儕腦力激盪,借助不同背景和知識來識別和選擇設計概念。

「如果你只有一把鐵鎚,全世界看起來都像釘子。」過度依賴自身經驗可能導致套用不適當的解決方案。

選擇設計概念#

識別替代方案後,透過建立優缺點對照表來選擇最合適的方案,也可使用 SWOT 分析等方法。選擇時需注意:

  • 限制條件可能排除某些替代方案(如授權許可限制)
  • 先前迭代的設計決策可能因不相容性而限制當前的選擇(如早期選擇 web 架構後,就不宜再選擇桌面 UI 框架)

何時該建立原型?#

如果分析技術無法引導你做出合適的選擇,可能需要建立拋棄式原型(throwaway prototype)來收集量測數據。當以下多數問題的答案為「是」時,強烈建議建立原型:

  • 專案是否採用新興技術?
  • 該技術是否對公司而言是新的?
  • 某些驅動因子(特別是品質屬性)的滿足是否存在風險?
  • 是否缺乏可信資訊來確認技術可行性?
  • 是否有需要測試的配置選項?
  • 所選技術是否能與專案中其他技術輕鬆整合?

Value of Information (VoI) 技術可以幫助團隊決定是否值得投入成本進行實驗。VoI 使用貝氏定理計算兩個量:EVPI(完美資訊的預期價值)和 EVSI(不完美資訊的預期價值),前者表示在實驗能提供確定結果時你應願意支付的最高金額,後者則考慮實驗結果可能不是 100% 確定的情況。

深入 Step 5:產出結構#

設計概念本身無法滿足驅動因子,除非你產出結構(structures)——即從選定的設計概念中識別和連接元素。這是 ADD 中架構元素的「實例化」階段。

回顧 Chapter 1,結構可分為三大類:

  • Module 結構:由開發期間存在的元素組成(如檔案、模組、類別)
  • Component and Connector (C&C) 結構:由執行期間存在的元素組成(如 process、thread)
  • Allocation 結構:由軟體元素和非軟體元素共同組成(如檔案系統、硬體、開發團隊)

實例化一個設計概念可能同時影響多個結構。例如,實例化 Passive Redundancy(warm spare)模式會同時產生 C&C 結構和 Allocation 結構。

不同設計概念的實例化方式#

  • Reference Architectures:通常需要進行客製化,新增或移除參考架構定義的結構中的元素
  • Patterns:提供泛型結構(含元素、關係、責任),需要將其轉化為特定結構。例如 Client-Server 模式定義了基本的計算元素和關係,但未規定客戶端和伺服器的數量、功能或通訊協定
  • Tactics:不規定特定結構,可透過修改已使用的其他設計概念來實現,或採用已實現該戰術的設計概念
  • Externally Developed Components:可能需要也可能不需要建立新元素。例如 OO 框架可能需要建立繼承自基底類別的新類別;而配置現有技術的選項則不需建立新元素

分配責任與識別屬性#

實例化元素時,需考慮分配給這些元素的責任。遵循的設計原則是:元素應具有高內聚(high cohesion)、窄責任集低耦合(low coupling)。

同時需考慮元素的屬性,如配置選項、狀態性、資源管理、優先級,甚至硬體特性。

建立元素間的關係#

建立結構也需要決定元素間的關係及其屬性。以 Client-Server 模式為例,需要決定:

  • 哪些客戶端與哪些伺服器通訊
  • 使用哪些 port 和 protocol
  • 通訊是同步還是非同步
  • 誰發起互動
  • 傳輸多少資訊、速率如何

定義介面#

介面建立了元素之間協作和交換資訊的契約規格

  • 外部介面(External Interfaces):系統必須互動的其他系統的介面,通常構成限制條件
  • 內部介面(Internal Interfaces):設計概念實例化所產生的元素之間的介面

行為表示法如 UML 序列圖、狀態圖和活動圖可以建模元素之間的資訊交換。介面的識別在各迭代中不是均等進行的——早期迭代產生的抽象元素(如 layers)其介面通常是欠規格的,隨著設計推進才逐步精煉。

深入 Step 6:設計過程中的初步文件#

Figure 20.4: Example preliminary documentation

記錄視圖草圖#

產出結構時,應同時建立初步文件:

  • 使用白板、翻頁紙、繪圖工具或建模工具繪製結構草圖
  • 如果使用非正式符號,應保持符號使用的一致性,最終添加圖例以避免歧義
  • 立即寫下分配給元素的責任——在識別元素的當下記錄,比事後統一記錄更容易且更可靠
  • 一種簡單方式:拍攝白板草圖的照片,貼入文件中,配以描述每個元素責任的表格

記錄設計決策#

每次迭代中做出的重要設計決策應被記錄,包括做出決策的理由(rationale)。當你檢視代表架構的圖表時,你看到的是思考過程的最終產物,卻不一定能理解達成這個結果的決策過程。記錄設計理由對於後續分析和理解至關重要。

文件的三個目的是分析建構教育。在設計階段,應根據風險緩解需求選擇文件目的,然後針對該目的進行記錄。例如,若有關鍵的品質屬性情境需要證明設計能滿足,就必須記錄分析所需的資訊。

深入 Step 7:追蹤設計進度#

在迭代結束時,需要評估:已完成多少設計?是否做了足夠的設計?是否已完成?

架構待辦清單(Architectural Backlog)#

架構待辦清單是設計過程中仍需執行的待辦事項。初始內容為驅動因子,但也可以包括:

  • 建立原型以測試特定技術或處理品質屬性風險
  • 探索和理解既有資產(可能需要逆向工程)
  • 設計決策審查中發現的問題

隨著設計推進,可能會新增項目。例如選擇了某個 reference architecture 後,發現它不提供 session management,這就成為需要加入待辦清單的關切。

設計看板(Design Kanban Board)#

Figure 20.5: A Kanban board used to track design progress

看板將待辦項目分為三個類別:

  • Not Yet Addressed:尚未處理
  • Partially Addressed:部分處理
  • Completely Addressed:完全處理

運作方式:

  1. 設計輪次開始時(Step 1),所有待辦項目位於「Not Yet Addressed」欄
  2. 開始迭代時(Step 2),相關驅動因子移至「Partially Addressed」欄
  3. 迭代完成且分析確認驅動因子已處理(Step 7),項目移至「Completely Addressed」欄

必須建立明確的移動標準。例如,「Completely Addressed」的標準可能是驅動因子已被分析或已在原型中實作,並確認需求已被滿足。理想情況下,設計輪次在大多數驅動因子(至少最高優先的)都位於「Completely Addressed」欄時結束。

本章總結#

設計是困難的,需要方法使其更易於處理且可重複。ADD 方法允許以系統化且具成本效益的方式設計架構。其核心要點包括:

  • 設計概念的識別與選擇:利用既有最佳實踐、自身經驗和同儕知識,識別 tactics、patterns、reference architectures 和外部元件等替代方案
  • 產出結構:從設計概念中實例化元素,分配責任,建立關係,定義介面
  • 初步文件:在設計過程中記錄視圖草圖和設計決策及其理由
  • 追蹤進度:使用架構待辦清單和看板追蹤設計進度,以風險為指引決定是否需要更多迭代