為何需要重新定義「複雜」#

Chapter 1 確立了耦合的角色:耦合是把系統黏起來的必要力量。那麼讓系統變得失序、難以管理的力量是什麼?答案是複雜度(complexity)

要管理複雜度,先要能定義它、辨認它。本章引入 Dave Snowden 提出的 Cynefin 框架,給「複雜」一個夠精準、可操作的定義。

Cynefin 是威爾斯文,發音類似「kuh-nev-in」(Dan North 的口訣是「念 Kevin,但中間打個噴嚏」)。

複雜度的直覺定義#

我們常憑直覺使用「複雜」這個詞,但精確下定義並不容易。本書採取的工作定義是:

複雜度反映人在面對某個系統時的認知負擔(cognitive load)。認知負擔越大,就越難理解、控制、預測這個系統。

軟體設計中,複雜度的代價特別具體:

  • 元件像拼圖,無法單看一塊就理解功能,必須拼起來才能看懂
  • 想修改系統時,難以判斷該動哪裡、改了之後會牽動什麼
  • 越複雜,修改所需的努力越多

複雜度是主觀的:對你而言複雜,對另一個專家可能簡單。例如汽車毛病對車主可能棘手數週,對資深技師可能十分鐘搞定。

正因為主觀,討論軟體設計時需要更精確的模型——這就是 Cynefin 的價值。

Cynefin 的五個領域#

Cynefin 把決策情境分成五個領域。前四個是核心,第五個(disorder)是「不知道自己在哪一個」的退路。

Clear(清晰)#

  • 行動的後果明確且可預測
  • 有規則或最佳實踐可循
  • 決策流程:Sense → Categorize → Respond
  • 例子:紅綠燈——識別號誌、對應規則、依規則停或走

Complicated(繁雜)#

  • 屬於「已知的未知(known unknowns)」:你知道自己缺什麼知識,可以找專家補
  • 決策流程:Sense → Analyze → Respond
  • 例子:車子壞掉,你不知道原因,但可以找技師診斷、依其建議修

Complex(複雜)#

  • 屬於「未知的未知(unknown unknowns)」:你不知道自己缺什麼,或這份知識根本不存在,因此找不到專家
  • 結果跟脈絡綁在一起,沒有任何通用建議能準確預測
  • 決策流程:Probe → Sense → Respond——必須先做安全實驗,觀察結果,再決定下一步
  • 例子:A/B 測試。沒人能事先精準預測哪個按鈕顏色 CTR 較高,只能先放出去看數據

Figure 2.1: A/B 測試是複雜領域中決策的常見範例

在複雜領域中,失敗是學習過程的必要組成部分。預期單一實驗能解答一切,本身就是錯誤的期待。

Chaotic(混沌)#

  • 因果關係根本斷裂,連回顧都看不出
  • 沒有專家可問、沒有實驗可做(不可能或結果隨機)
  • 決策流程:Act → Sense → Respond——憑直覺先做動作把局面拉回複雜領域,再分析
  • 例子:擲骰子、玩輪盤;或火災等緊急狀況,根本沒時間實驗

Disorder(失序)#

  • 你不知道自己究竟在哪個領域
  • 唯一的行動是「先辨認出當前屬於哪一個領域」

較新版本的 Cynefin 把 disorder 細分為 aporia(你意識到自己缺資訊)與 confusion(你誤判了領域而不自知)。本書為求簡潔不做區分。

四個領域的差異對照#

四個領域的核心差別在於因果關係的耦合程度

領域因果關係所需知識行動方式
Clear緊耦合已知分類(Categorization)
Complicated緊耦合但不顯而易見已知的未知分析(Analysis)
Complex鬆耦合未知的未知實驗(Experimentation)
Chaotic解耦「不可知」信任直覺

把這個觀念帶回耦合主題:複雜度本身就是「行動」與「結果」之間的鬆耦合

軟體設計中的 Cynefin#

Cynefin 不只是哲學工具,也能直接指導軟體設計決策。書中以兩個情境示範。

範例 A:整合外部服務 NotificationMaster#

需要送 SMS,考慮整合既有的 NotificationMaster.SendSMS。同樣需求,依細節差異可能落在四個領域:

  • Clear:方法接受 PhoneNumber 型別,建構子明確要求 E.164 國際格式

Figure 2.2: 整合外部元件——清晰(Clear)

  • Complicated:方法只接受 string,文件未說明格式——但你可以去問模組作者

Figure 2.3: 整合外部元件——繁雜(Complicated)

  • Complex:模組屬於 legacy 系統,沒人懂、看不到原始碼,只能不斷試誤找出可用格式
  • Chaotic:API 後方有 load balancer 指向不同版本的服務,相同輸入時而成功時而失敗

Figure 2.4: 整合外部元件——混沌(Chaotic)

注意一個有趣的轉換:在 Complex 領域中試出可用格式之後,下一個整合者可以「諮詢你」,於是同樣的問題就降為 Complicated。領域是會隨知識累積而轉移的。

範例 B:修改資料庫索引#

修改 RDB 索引可能造成什麼影響?

  • Clear:資料庫專屬於你的微服務,所有查詢都在你掌控之內

Figure 2.5: 修改資料庫索引——清晰(Clear)

  • Complicated:另有一個團隊使用部分資料,但你知道是哪個團隊,可以協調

Figure 2.6: 修改資料庫索引——繁雜(Complicated)

  • Complex:你知道有別人在用,但不知道是誰、用法為何——只能靠 staging 上的整合與效能測試「探測」
  • Chaotic:你完全不知道有人在用,沒有自動化測試保護,部署後另一個元件開始 timeout——只能憑直覺先 rollback

Cynefin 與「複雜度」的精確意義#

Cynefin 幫我們把日常語言中的「複雜」收斂成更精確的定義:

  • 認知負擔高,不一定就是 complex——若有專家可問就只是 complicated
  • 完全沒有因果關係不是 complex,那是 chaotic

全書接下來統一採用 Cynefin 的定義:複雜(complex)= 高度不確定,因果關係鬆耦合,需要安全實驗才能揭示因果

英文中 complexcomplicated 常被當成同義詞。Cynefin 刻意把兩者分開,源自拉丁文也支持這種區分:

  • complicated:源自 complicare(折疊在一起)
  • complex:源自 complexus(部件的聚合)

重點整理#

做設計決策前,先問自己:「我現在身處哪個 Cynefin 領域?」對應該採用 Sense-Categorize-Respond、Sense-Analyze-Respond、Probe-Sense-Respond,還是 Act-Sense-Respond?

每當你發現自己「先做個小實驗才敢決定」,停下來想一想——你正在處理的就是複雜性。

下一章會延伸這個討論:在「系統」的脈絡中,複雜度究竟是怎麼長出來的?