一套運行中的系統累積出三十多個錯誤代碼、每個功能模組各自定義錯誤類型、三種拋出方式並存時,要處理的是一個橫跨全系統的約定該怎麼在不停機的前提下換掉。單一模組的錯誤處理修得再乾淨,都不改變這個狀態。

分散的不一致會互相強化

這種狀態通常由三個互相強化的問題組成。

錯誤分類過度細化。三十多個錯誤代碼聽起來精確,而精確與可用是兩件事:使用這套代碼的人要記住的量超過工作記憶,功能邊界模糊時分類判斷本身就要花時間。過度分類創造的是新的複雜性。

效能宣稱缺乏測量。熱路徑中的運行時字串拼接累積出成本,而沒有測量數據時,成本的大小只是估計。估計的方向通常偏樂觀——沒有人會估一個讓自己要立刻停下來處理的數字。

跨模組一致性缺失。不同模組使用不同的錯誤處理模式,在模組間切換時要換一次心智模型。

1// 同一系統中並存的三種錯誤處理風格
2// 模組 A:拋出字串
3throw 'OPERATION_FAILED';
4
5// 模組 B:自訂 Exception 類別
6throw CustomException('MODULE_B_ERROR', details);
7
8// 模組 C:使用通用 Exception
9throw Exception('Generic error message');

三種模式各自需要不同的測試策略,跨系統傳輸時序列化邏輯也各自處理。維護成本隨模式數量成長的曲線比線性陡。

分散的問題要統一解,而不是逐處修

面對這種狀態,直覺反應是逐一修復:修模組 A、修模組 B、再修模組 C。這條路走不通——每一次局部修正都在跟其他模組的既有模式接界,修了一處會在交界處長出新的不一致。

方向是統一的解決方案。而統一不等於一次性全部替換:系統在運行、使用者在使用,完整重寫的風險落在生產環境上。設計問題因此變成:怎麼在不停機的前提下,從舊系統平穩遷移到新系統。

橋接模式讓新舊並行

橋接層讓舊系統與新系統同時運行,支援四種模式:

  • 向後相容優先:新系統呼叫舊格式,確保現有整合不中斷
  • 新系統優先:新的程式碼優先使用新格式,舊程式碼仍可透過橋接運作
  • 雙系統驗證:同時在兩套系統中驗證結果,用於關鍵期的安全確認
  • 逐步遷移:按功能模組分批切換,控制每次的變更範圍

四種模式共同給出的性質是:遷移可以分批進行、隨時暫停,而任何一批出問題的影響範圍限制在那一批。

適配器層負責語意不流失

橋接處理「怎麼並行」,適配器處理「怎麼轉換」。

每個功能模組有專屬的適配器,把舊錯誤格式映射到新格式。關鍵在映射要顯式:每個舊錯誤代碼對應一個明確的新類型,帶著錯誤嚴重程度與建議的恢復策略。

 1// 模組特化適配器:每個映射關係都是顯式定義的
 2static const Map<String, ErrorMapping> errorMapping = {
 3  'OLD_VALIDATION_ERROR': ErrorMapping(
 4    newType: 'VALIDATION_ERROR',
 5    severity: Severity.moderate,
 6    recovery: Recovery.userInputRequired,
 7  ),
 8  'OLD_NETWORK_TIMEOUT': ErrorMapping(
 9    newType: 'TIMEOUT_ERROR',
10    severity: Severity.high,
11    recovery: Recovery.automaticRetry,
12  ),
13};

沒有模糊映射,沒有近似替換。舊錯誤代碼找不到對應的新類型時,系統明確報錯而不是靜默轉換成最接近的那一個——靜默轉換會把語意流失推遲到執行期,而那時已經沒有映射表可以查。

遷移前要先量的東西

遷移的成效由前後兩次測量的差構成,所以測量要在動手之前先做一次:錯誤類型的實際數量、熱路徑的執行成本、測試套件的通過狀態與覆蓋範圍。沒有遷移前的數據,遷移後的任何改善宣稱都只是印象。

同樣要在動手前查清楚的是現狀的依賴形狀:現有系統的哪些部分互相依賴、哪些模組的改動風險最高、有哪些隱性的使用約定沒有寫進文件。這些問題在遷移過程中才發現的話,發現的地點會是一個已經改到一半的系統。

自動化優先,並準備人工備案

能自動化的不手工處理。這除了效率,主要是正確性:大量重複的機械操作由人執行時,錯誤率不會是零,而錯誤散落在幾百處修改裡很難被抽查抓到。每個遷移步驟建立自動化工具、配套多層驗證。

同時要認清工具的能力邊界。自動化處理不了的邊界情況一定存在,事前準備人工處理的方案,遷移才不會卡在那裡等工具被改好。

四個常見陷阱

低估複雜度。表面上是「換一種寫法」的遷移,往往涉及語意上的細微差異與大量邊界情況。完整跑一次現有測試套件、把現狀分析做完,是不能省的步驟。

忽視相容性。急於達到目標狀態而略過過渡期需求,是遷移失敗的直接原因之一。向後相容策略在一開始就設計,不是遇到問題時臨時補。

工具過度依賴。工具無法處理的邊界情況若沒有備案,遷移會停在那裡。

缺乏回滾計畫。只考慮成功情況的遷移計畫是不完整的。每個階段都要有明確的回滾方案,而且在實際執行前演練過——問題發生的當下不會有時間從零設計恢復流程。

四個設計原則

統一性優於客製化。一致的介面與行為模式,長期維護成本低於為每個特殊需求提供特化方案。

測量優於估計。效能是否真的改善、覆蓋率是否真的提高,在有數據之前都是猜測。

漸進優於激進。可控的小步前進比一次性大幅重寫更容易發現問題,也讓每一步的回滾範圍有界。

自動化優於手工。把判斷與轉換邏輯編碼進工具,讓錯誤在流程中被機制攔截,而不是依賴事後的人工審查。

大規模遷移的技術風險與變更範圍同時存在,而核心思路可以拆成三件事:統一解決分散的問題、用橋接與適配器確保過渡期安全、用遷移前後的測量確認改善是真的。

架構違規要在 commit 階段就被擋下來的做法,走 架構合規交給機制;遷移拆成 Ticket 的粒度判斷,走 Atomic Ticket 方法論