本章提供如何建構自己的 trade-off 分析的建議,使用本書中推導結論的相同技術。

現代 trade-off 分析的三步驟流程:

  1. 找出哪些部分是糾纏在一起的(Find what parts are entangled together)
  2. 分析它們如何耦合(Analyze how they are coupled to one another)
  3. 評估 trade-offs:判斷對相互依賴系統的變更影響(Assess trade-offs by determining the impact of change to interdependent systems)

Finding Entangled Dimensions#

架構師的第一步是發現哪些維度是糾纏(entangled)或編織(braided)在一起的。這對每個特定架構而言是獨特的,需要由熟悉整體生態系統的資深開發者、架構師、維運人員等來發現。

Coupling#

  • 分析的第一部分回答:架構中的各部分如何彼此耦合
  • 最直覺的定義:如果改變 X,是否可能迫使 Y 也要改變?
  • 團隊可以手動或透過自動化建構 static coupling diagram(靜態耦合圖)

建構微服務的靜態耦合圖需要收集:

  • 作業系統 / 容器相依性
  • 透過傳遞式相依性管理交付的相依性(frameworks、libraries 等)
  • 持久化相依性(資料庫、搜尋引擎、雲端環境等)
  • 服務啟動所需的架構整合點
  • 訊息基礎設施(如 message broker)

靜態耦合圖不考慮僅透過 workflow 通訊的其他量子。例如 AssignTicket 與 ManageTicket 在 workflow 中合作,但若無其他靜態耦合點,它們是靜態獨立的(但在實際 workflow 中動態耦合)。

Analyze Coupling Points#

  • 識別耦合點後,下一步是以輕量級方式建模可能的組合
  • 目標是判斷哪些力量需要 trade-off 分析
  • 本書中,作者選擇 coupling、complexity、responsiveness/availability、scale/elasticity 作為主要 trade-off 關注點,加上三個動態量子耦合力量:communication、consistency、coordination

動態耦合模式的整合比較(Table 15-2):

PatternCoupling levelComplexityResponsiveness/availabilityScale/elasticity
Epic SagaVery highLowLowVery Low
Phone Tag SagaHighHighLowLow
Fairy Tale SagaHighVery lowMediumHigh
Time Travel SagaMediumLowMediumHigh
Fantasy Fiction SagaHighHighLowLow
Horror StoryMediumVery highLowMedium
Parallel SagaLowLowHighHigh
Anthology SagaVery lowHighHighVery high

從矩陣中觀察到的重要關聯:

  • Coupling level 與 scale/elasticity 呈直接反比:耦合越高,可擴展性越差
  • Responsiveness/availability 與 coupling level 也有類似的關聯:耦合越高,回應性和可用性越低
  • 這體現了迭代式架構(iterative architecture)的重要性:沒有架構師能一眼看透所有細微差異

Assess Trade-Offs#

  • 建立允許迭代式「what if」情境的平台後,聚焦於基本的 trade-offs
  • 例如選擇同步 vs. 非同步通訊,這會限制後續的選擇
  • 架構團隊可以反覆進行此過程,直到解決所有困難的決策——即具有糾纏維度的決策
  • 解決完糾纏的決策後,剩下的就是設計(What’s left is design)

Trade-Off Techniques#

Qualitative Versus Quantative Analysis#

  • 本書的 trade-off 表格幾乎都不是定量的(quantitative),而是定性的(qualitative)
  • 衡量品質而非數量,因為兩個架構總是有足夠差異,無法進行真正的定量比較
  • 但透過對大型資料集的統計分析,可以進行合理的定性分析
  • 例如比較模式的可擴展性時,觀察多種 communication、consistency、coordination 組合的實作

建議磨練定性分析的技能,因為在架構中真正的定量分析機會很少。可以在組織內或透過局部實驗(localized spikes)來驗證理論。

MECE Lists#

  • MECE(Mutually Exclusive, Collectively Exhaustive)是從技術策略領域借用的概念
  • 確保架構師比較的是同類事物,而非截然不同的東西

兩個要素:

  • Mutually exclusive(互斥):比較的項目之間不能有能力重疊。例如,將簡單的 message queue 與包含 message queue 及許多其他元件的 ESB 進行比較是無效的
  • Collectively exhaustive(窮盡):確保涵蓋了決策空間中的所有可能性。例如評估高效能 message queue 時,若只考慮 ESB 和簡單 message queue 而忽略 Kafka,就沒有窮盡所有選項

Figure 15.1: A MECE list is mutually exclusive and collectively exhaustive

MECE list 的目標是完整覆蓋一個類別空間,沒有空洞也沒有重疊。做出有長期影響的決策時,確保比較標準是 collectively exhaustive 的,以鼓勵探索新出現的能力。

The “Out-of-Context” Trap#

  • 評估 trade-offs 時,必須將決策保持在正確的脈絡中
  • 否則外部因素會不當影響分析
  • 架構師需要平衡的是正確的 trade-off 集合,而非所有可用的

範例:shared service vs. shared library

Figure 15.2: Deciding between shared service or library in a distributed architecture

  • 從一般性分析來看,shared library 方案在 trade-off 矩陣中明顯勝出

Figure 15.3: Trade-off analysis for two solutions

  • 但當加入額外脈絡(例如「我們使用多語言程式設計,服務用四種不同語言撰寫,效能和容錯不是我們的關注點」),決策會翻轉為 shared service

Figure 15.4: Shifting decision based on additional context

  • 找到正確的脈絡可以讓架構師考慮更少的選項,大幅簡化決策

通用解決方案在真實世界的架構中很少直接適用,必須加入情境脈絡才有意義。理解迭代式設計的重要性——透過圖解和定性「what-if」遊戲來探索解決方案。

Model Relevant Domain Cases#

  • 架構師不應在真空中做決策,應加入與特定方案相關的領域驅動因素
  • 建模具體的領域場景可以幫助過濾選項,聚焦於真正重要的 trade-offs

範例:單一支付服務 vs. 每種支付類型一個服務

Figure 15.5: Choosing between a single payment service or one per payment type

  • 場景 1(更新信用卡處理服務):分開的服務提供更好的 maintainability、testability、deployability

Figure 15.6: Scenario 1: update credit card processing service

  • 場景 2(新增支付類型):分開的服務展現 extensibility 優勢

Figure 15.7: Scenario 2: adding a payment type

  • 場景 3(使用多種支付類型):需要 orchestrator 進行協調,而 orchestrator 會負面影響效能並增加資料一致性的挑戰

Figure 15.8: Scenario 3: using multiple types for payment

  • 最終歸結為:performance and data consistency(單一服務)vs. extensibility and agility(分開的服務)

Prefer Bottom Line over Overwhelming Evidence#

  • 架構師容易積累大量資訊來學習 trade-off 分析的所有面向
  • 但許多技術細節對非技術利害關係人而言太深奧
  • 應將 trade-off 分析精簡為幾個關鍵重點

範例:同步 vs. 非同步通訊(信用卡處理)

同步優勢同步劣勢非同步優勢非同步劣勢
客戶必須等待信用卡核准流程啟動不需等待流程啟動
保證在客戶請求結束前流程已啟動無法保證流程已啟動
orchestrator 掛掉時客戶申請被拒申請提交不依賴 orchestrator
  • 建模完場景後,可以為利害關係人建立 bottom-line 決策:哪個更重要——保證信用卡核准流程立即啟動,還是回應性和容錯性
  • 消除令人困惑的技術細節,讓非技術利害關係人聚焦於結果

Avoiding Snake Oil and Evangelism#

  • 技術傳教(evangelism) 是架構師的一大陷阱:過度推崇某個工具或方法時,會放大優點、縮小缺點
  • 在軟體架構中,trade-offs 永遠會回來找你——沒有任何東西是全好的
  • 對承諾「驚人新能力」的工具或技術保持警惕,要求誠實地評估好壞兩面

Figure 15.10: An architect evangelist who thinks they have found a silver bullet

範例:publish-and-subscribe vs. point-to-point messaging

  • 一位架構師偏好 publish-and-subscribe topic,因為它支持「架構的可擴展性」
  • 但加入 bid history 後,單一 topic 的問題浮現:
    • 為每個 consumer 建立不同合約的需求 → 實作了 Stamp Coupling 反模式
    • 資料安全問題:每個 consumer 都能存取所有資料
    • 操作特性差異:無法為不同 consumer 個別設定自動擴展

Figure 15.11: Scenario 1: Adding bid history to the existing topic

改用 point-to-point queue 的優勢:

  • 每個 consumer 可以有自己的合約
  • 安全存取和資料控制在每個合約中獨立管理
  • 每個 queue 可以獨立監控和擴展

Figure 15.12: Using individual queues to capture bid information

Point-to-pointPublish-and-subscribe
允許異質合約可擴展性(容易新增 consumer)
更細粒度的安全存取和資料控制
每個 consumer 有獨立的操作設定檔

不要讓他人強迫你傳教某件事——回歸 trade-offs。架構師應避免傳教,努力成為 trade-offs 的客觀仲裁者。架構師為組織帶來的價值不是追逐銀彈,而是磨練分析 trade-offs 的技能。

Sysops Squad Saga: Epilogue#

  • 團隊體認到:不能依賴通用建議來建構自己的架構,每個架構都是獨特的
  • 必須持續做 trade-off 分析的「hard work」
  • 這不是劣勢,而是優勢:學會隔離維度並進行 trade-off 分析,就是在學習自己架構的具體知識

Testing is the engineering rigor of software development. 軟體工程師雖然沒有結構工程師那樣的數學工具,但可以透過增量式地建構和測試解決方案,利用更靈活的媒介的優勢。透過客觀結果測試,trade-off 分析可以從定性走向定量——從臆測走向工程。