為什麼要談「易變性」#

想像一個極度耦合的系統,元件之間共享了大量無關的知識,甚至有 intrusive coupling。技術上來說它確實是強耦合。

但若這個系統的元件從來不會改變呢?「連動修改」的可能性,在這時還重要嗎?

本章把焦點轉到耦合的時間維度——易變性(volatility):模組預期變動的頻率。重點是學會評估元件的易變性,並把它與整合強度合在一起看。

變更與耦合#

敏捷的核心信念之一:「重視回應變更,勝於依循計畫」。變更代表新機會、對業務的新理解、更好的實作方式——是健康系統的徵兆。

但開發者並不總是歡迎變更。常見的痛苦:

  • 優雅的設計被一個小需求變更打回原形
  • 為了適應新規則,到處塞 if-else
  • 漂亮的微服務系統一遇到功能變更就變成 distributed Big Ball of Mud

共通元素是複雜互動。變更會把隱性複雜度暴露出來——一個變更竟然牽動「應該已解耦」的多個元件,正是隱性互動現形的瞬間。

反過來說,永不變動的元件即使設計不佳,也未必是嚴重問題。所以要全面評估耦合的影響,就必須評估元件的變動率。

軟體為什麼會變#

軟體設計圍繞兩個空間:

  • 問題空間(problem space):定義業務問題的所有活動
  • 解決空間(solution space):軟體解法本身——設計、架構、實作

解決空間的變更#

問題不變,解決方案仍可能變。常見原因:

  • 修 bug:小到打字錯誤,大到漏掉的業務規則
  • 技術債:越晚還,代價越高
  • 重構:改進結構、調整封裝邊界
  • Conway’s Law 驅動:組織結構變了 → 系統設計被迫對齊

Conway’s Law 帶來的演化#

  • 小新創時期:團隊小、目標一致,介面變更可在飲水機旁解決
  • 變大公司後:跨團隊協作,需要正式整合協定,變更需要計畫與協調

為了減少團隊互踩,系統設計應該對齊組織溝通結構。團隊距離越遠,元件之間的距離應該越遠(生命週期耦合越低)——這既是獨立性的保障,也是改動成本的代價。

即使遠距工作,組織距離仍然存在——並非物理而是組織邏輯。團隊內溝通先天比跨團隊有效,公司越大跨團隊溝通越低效。這不是反對遠距,而是設計時必須納入的組織因素。

問題空間的變更#

「在水上行走和依規格開發軟體都很簡單,只要兩者都被凍結。」——Edward V. Berard

需求不會凍結。新功能、行為調整、業務洞見、客戶需求都會推著系統變。在中型以上的專案,你會發現某些元件變得特別頻繁——為什麼?哪些元件會這樣?

評估變更率#

領域分析(DDD)#

要設計好軟體,必先理解業務問題。Domain-Driven Design 提供一套詞彙來描述業務領域。

業務領域(Business Domain)#

公司提供給客戶的整體服務範圍:

  • FedEx → 快遞
  • Walmart → 零售
  • Amazon → 零售 + 雲端運算

業務領域並非靜態。Nokia 從橡膠製造演進到電信業,就是經典案例。

子領域(Subdomain)#

Figure 9.1: 子領域可視為一組互相關聯的 use cases

子領域是業務領域中更細的活動單位,是公司能在領域內運作的「業務積木」:

  • 從組織單位(會計、行銷、業務)著手識別
  • 技術角度:一組互相關聯的 use cases,操作相關資料、實作相關功能

子領域 ≈ 一群「functionally coupled」的 use cases——通常存在 temporal/sequential 或 transactional 關係。

WolfDesk 的子領域:

  • Identity & Access
  • Support Case Management
  • Distribution
  • Desk Management
  • Knowledge Base
  • Billing

DDD 把子領域分為三類:

Core Subdomains(核心子領域)#

提供公司競爭優勢的功能——獨家技術、優化過的流程、獨特知識、智財。

  • 目的:讓公司與競爭對手有差別
  • 特性:複雜,因為簡單問題不會構成競爭優勢
  • Cynefin:屬 complex 領域,需要不斷實驗
  • 易變性最高——既因為一開始就要試錯,也因為競爭對手會跟進,必須持續演進

WolfDesk 的核心子領域可能包括:

  • Support case management(自動化回應、狀態轉換的優化)
  • Distribution(依案件、專業、過往經驗匹配最適 agent)
  • Knowledge base(自動撈出每個案件相關的文件)

識別核心子領域的方法:

  • 找出公司與競爭對手的差異點,挖出它的「secret sauce」
  • 在棕地專案中,看哪些區域最受業務關注、需求變動最頻繁

Generic Subdomains(通用子領域)#

採用既有的、被驗證過的解決方案(COTS 商用、開源)。

  • 目的:解決有共通解的複雜問題
  • 特性:複雜(所以前人才花心力),但門檻低(人人都拿得到同一份解)
  • Cynefin:屬 complicated 領域——找供應商這個專家就行
  • 易變性——除了安全性更新,鮮少劇烈變動

自己寫加密演算法?把資源花在 generic 子領域,是浪費你能花在核心子領域的能量。

WolfDesk 的 Identity & Access 與 Billing 屬於 generic(用商用 SaaS)。

Supporting Subdomains(支援子領域)#

介於兩者之間:必須自己解,但解法簡單,沒有競爭優勢。

  • 特性:業務邏輯直接、進入門檻低、競爭對手能快速複製,但複製了也無關公司勝負
  • Cynefin:屬 clear 領域——因果關係明顯,解法明顯
  • 易變性——業務不會花力氣優化它

戰略上,公司會樂見有人把 supporting 子領域變成 generic(提供現成解),讓自己少花心力在非關鍵業務上。

WolfDesk 的 Desk Management(多為資料輸入畫面)屬 supporting。

子領域類型對照#

子領域競爭優勢複雜度易變性問題類型
CoreInteresting
GenericSolved
SupportingObvious

原始碼控管分析#

對棕地專案,從 git history 統計每個模組的 commit 次數。Commit 越多,通常越易變。

但這個指標有兩種偏誤:

False Positives(偽陽性)#

不是所有 commit 都同等重要。修 bug 與引入新功能要分開看——後者更能指向核心子領域。

False Negatives(偽陰性)#

低 commit 頻率可能是「被迫」的。作者曾遇到一個本應屬於 core 的模組,commit 卻很少——原因是程式碼一團亂,每次改都引發大規模故障,業務最後乾脆放棄改它,把心力轉到別的地方。

易變性 × 整合強度#

同樣強度,截然不同的命運#

Figure 9.2: 兩個系統擁有相同元件數與相同的整合強度

Figure 9.3: 同樣的元件,但子領域類型不同,命運也不同

考慮兩個系統,元件數一樣、整合強度也一樣。它們的設計品質一樣嗎?把每個元件對應到子領域類型後就能看出差別:

  • 系統 A:與 core 子領域元件之間都是 contract coupling
  • 系統 B:與 core 子領域元件之間是 intrusive 與 functional coupling

核心子領域必然頻繁變動。系統 B 的變動會無情地波及所有依賴它的元件;系統 A 在「最重要的邊界」上把共享知識壓到最低,因此更穩定。

推導出的易變性(Inferred Volatility)#

Figure 9.4: 一個實作支援子領域的元件(初始範例)

Figure 9.5: 對易變元件採取高整合強度,將易變性向下游傳染

元件的易變性不能只看自己,還要看它依賴的元件。

考慮一個元件 A 實作 supporting 子領域,理論上應該是低易變。但若它透過 intrusive coupling 依賴三個 core 子領域元件呢?

每次任一上游 core 元件改動,A 都要跟著動 → A 的實際易變性被拉高到接近 core 子領域。A 的子領域類型變成「無關緊要的標籤」,真正決定它易變性的,是它所依賴的元件 + 整合強度。

重點整理#

評估系統時別只看每個元件本身:

  • 識別子領域類型 → 推估「天生易變性」
  • 結合整合強度 → 推估「實際易變性」
  • 在最易變的地方使用最弱的耦合,是設計穩定系統的關鍵之一

易變性可以來自多個來源:

  • 業務領域本質(核心 vs 支援 vs 通用)
  • 技術改善(重構、技術債)
  • 組織結構變化(Conway’s Law)
  • 系統設計本身(高強度依賴於易變元件)

至此,三個耦合維度——強度(strength)、距離(distance)、易變性(volatility)——都已備齊。下一章開始 Part III,把這三個維度整合成評估與決策的框架:Balanced Coupling