可靠性的代價是對極致簡潔的追求。 — C.A.R. Hoare,圖靈獎演講

軟體系統天生動態而不穩。本章談 SRE 為什麼要花力氣維持簡潔——並把簡潔視為可靠性的前提。

穩定 vs. 敏捷#

SRE 的工作可以總結為一句話:讓系統的敏捷度與穩定性保持平衡。

少數情況可以為了敏捷犧牲穩定——例如做「探索性編碼(exploratory coding)」:刻意給程式碼一個保存期限,允許試錯,因此測試與發佈門檻可放寬。

但對絕大多數生產系統,要求是平衡。SRE 經驗顯示:可靠的流程其實會提升開發敏捷度——

  • 快速、可靠的上線讓變更後果可見
  • bug 出現後更快被定位與修復
  • 開發者因此能把注意力放在真正的功能與效能上

無趣是美德#

Robert Muth(Google 工程師):「不像偵探小說,原始碼沒有刺激、懸疑與謎題反而是好事。」生產環境的驚喜是 SRE 的敵人。

本質複雜度 vs. 偶發複雜度#

引用 Fred Brooks「No Silver Bullet」:

  • 本質複雜度(essential complexity):問題本身內含、無法移除
  • 偶發複雜度(accidental complexity):因實作選擇引入,可工程改善

例:寫 web server 要處理「快速回應」是本質複雜度;用 Java 寫導致需處理 GC 影響則是偶發複雜度。

SRE 應該:

  • 在偶發複雜度被引入系統時抵抗
  • 接手系統時持續清除既有的複雜度

我不要刪我的程式碼!#

工程師對自己寫的程式有感情,因此大規模清理時常會聽到:

  • 「以後可能會用到」
  • 「先註解掉就好」
  • 「用 flag gating 不要刪」

這些都是糟糕的建議:

  • 版控系統本來就能回溯,不需要保留註解碼
  • 大量註解掉的程式碼會在源碼演進過程中變成干擾
  • 永遠關閉的 flag 後面的死程式碼是定時炸彈(Knight Capital 的災難就是經典案例)

「負程式碼行數」這個指標#

對於 24/7 服務而言,每多一行新程式碼就多一份債

較小的專案更易理解、易測試、缺陷更少。最令人滿足的程式設計之一是一次刪除上千行不再被需要的程式碼。

實踐:

  • 嚴審程式碼是否真的服務業務目標
  • 例行清理 dead code
  • 在所有測試層級內建 bloat 偵測

最小化 API#

完美並不是已經無法再加,而是已經無法再減。 — Antoine de Saint Exupéry

API 是「簡潔」的清楚展現:

  • 提供愈少方法與參數,愈容易讓使用者理解
  • 我們愈能把心力投入在這些少數方法的品質上
  • 小而清晰的 API 通常代表「問題已被充分理解」

模組化#

物件導向程式設計的法則同樣適用於分散式系統:

  • Binary 之間、binary 與設定之間的鬆耦合同時促進敏捷與穩定
  • 子系統的 bug 可以獨立修復、獨立推上線
  • 對 API 做版本管理:使用者可繼續用舊版、安全地評估升級
  • 系統釋出節奏可分歧,不必每次都全量推送
  • 避免「util / misc」之類的雜湊垃圾桶——好的分散式系統由目的清晰的協作者組成
  • 資料格式也要模組化:Google 的 protocol buffers 的核心設計目標就是向前向後相容

發佈的簡潔性#

一次只動少數變更會比一次推 100 個變更好——可以類比為機器學習的梯度下降:每一步都評估改善或退化

大批變更同時上線,事後追責耗費極大;小批次反而能讓團隊更快推進、更有信心。

結語#

軟體簡潔是可靠性的前提。把每個步驟想得更簡單,並非懶惰,而是把「我們究竟想完成什麼、怎麼做最容易」釐清。

對一個功能說「No」並非限制創新——而是讓環境保持乾淨,讓焦點留在真正的工程與創新上。