系統調試
概述
隨機修復會浪費時間並產生新的錯誤。快速補丁掩蓋了根本問題。
核心原則: 在嘗試修復之前始終找到根本原因。症狀修復失敗。
**違反此過程的字面意思就是違反調試精神。 **
鐵律
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
如果您尚未完成第一階段,則無法提出修復建議。
何時使用
用於任何技術問題:
-
測試失敗
-
生產中的錯誤
-
意外行為
-
性能問題
-
構建失敗
-
整合問題
特別是在以下情況下使用此功能:
-
在時間壓力下(緊急情況讓人很容易猜測)
-
「只需一個快速解決方案」似乎是顯而易見的
-
您已經嘗試過多次修復
-
之前的修復不起作用
-
你沒有完全理解這個問題
在以下情況下不要跳過:
-
問題看起來很簡單(簡單的錯誤也有根本原因)
-
你很著急(著急保證返工)
-
經理希望立即修復(系統化比混亂更快)
四個階段
您必須先完成每個階段,然後才能進入下一階段。
第一階段:根本原因調查
嘗試任何修復之前:
仔細閱讀錯誤訊息
-
不要跳過過去的錯誤或警告
-
它們通常包含精確的解決方案
-
完整讀取堆疊追蹤
-
記下行號、檔案路徑、錯誤程式碼
一致地再現
-
你能可靠地觸發它嗎?
-
具體步驟是什麼?
-
每次都會發生嗎?
-
如果不可重現→收集更多數據,不要猜測
檢查最近的變更
-
是什麼變化可能導致這種情況?
-
Git diff,最近的提交
-
新的依賴項,配置更改
-
環境差異
收集多組件系統中的證據
當系統有多個元件時(CI → 建置 → 簽章、API → 服務 → 資料庫):
在提出修復建議之前,添加診斷工具:
For EACH component boundary:
- Log what data enters component
- Log what data exits component
- Verify environment/config propagation
- Check state at each layer
Run once to gather evidence showing WHERE it breaks THEN analyze evidence to identify failing component THEN investigate that specific component
示例(多層系統):
Layer 1: Workflow
echo "=== Secrets available in workflow: ===" echo "IDENTITY: ${IDENTITY:+SET}${IDENTITY:-UNSET}"
Layer 2: Build script
echo "=== Env vars in build script: ===" env | grep IDENTITY || echo "IDENTITY not in environment"
Layer 3: Signing script
echo "=== Keychain state: ===" security list-keychains security find-identity -v
Layer 4: Actual signing
codesign --sign "$IDENTITY" --verbose=4 "$APP"
**這揭示了:**哪一層失敗了(祕密→工作流程✓,工作流程→建構✗)
- 追蹤資料流
當錯誤深入呼叫堆疊時:
看root-cause-tracing.md 在此目錄中瞭解完整的向後跟蹤技術。
快速版本:
-
不良價值從何而來?
-
什麼叫這個價值不高?
-
繼續追蹤,直到找到源頭
-
從根源解決,而不是從症狀解決
第二階段:模式分析
修復前先找到圖案:
尋找工作範例
-
在同一代碼庫中找到相似的工作代碼
-
有什麼作品與已損壞的作品相似?
與參考文獻比較
-
如果實現模式,請完整閱讀參考實現
-
不要略讀 - 閱讀每一行
-
應用前充分了解模式
找出差異
-
工作和壞掉有什麼不同?
-
列出每一個差異,無論多麼小
-
不要認為“那不重要”
瞭解依賴關係
-
這還需要什麼其他組件?
-
什麼設置、配置、環境?
-
它做出了什麼假設?
第三階段:假設和測試
科學方法:
形成單一假設
-
明確說明:“我認為 X 是根本原因,因為 Y”
-
寫下來
-
要具體,不要含糊
最少測試
-
做出盡可能小的改變來檢驗假設
-
一次一個變量
-
不要一次修復多個問題
繼續之前先驗證
-
有效嗎?是 → 第 4 階段
-
沒起作用?形成新的假設
-
不要在頂部添加更多修復
當你不知道時
-
說“我不明白X”
-
別假裝知道
-
求人
-
研究更多
第四階段:實施
解決根本原因,而不是症狀:
建立失敗的測試用例
-
最簡單的再現
-
如果可能的話進行自動化測試
-
如果沒有框架,一次性測試腳本
-
修復前必須有
-
使用superpowers:test-driven-development 編寫正確的失敗測試的技能
實施單一修復
-
解決已確定的根本原因
-
一次更改一個
-
沒有“當我在這裡”的改進
-
沒有捆綁重構
驗證修復
-
現在測試通過了嗎?
-
其他測試沒有被破壞嗎?
-
問題真的解決了嗎?
如果修復不起作用
-
停止
-
數數:您嘗試過多少次修復?
-
如果 < 3:返回階段 1,用新信息重新分析
-
如果 ≥ 3:停止並質疑架構(下面的步驟 5)
-
在沒有進行架構討論的情況下,不要嘗試修復 #4
如果 3 個以上修復失敗:架構問題
指示架構問題的模式:
-
每個修復都會在不同位置揭示新的共享狀態/耦合/問題
-
修復需要“大規模重構”才能實施
-
每次修復都會在其他地方產生新的症狀
停下來詢問基本原理:
-
這種模式從根本上來說合理嗎?
-
我們是“純粹因為慣性而堅持下去”嗎?
-
我們應該重構架構還是繼續修復症狀?
在嘗試更多修復之前與您的人類合作夥伴討論
這不是一個失敗的假設——這是一個錯誤的架構。
危險信號 - 停止並遵循流程
如果你發現自己在想:
-
“現在快速修復,稍後再調查”
-
“嘗試改變X看看是否有效”
-
“添加多個更改,運行測試”
-
“跳過測試,我手動驗證”
-
“可能是X,讓我解決這個問題”
-
“我不完全明白,但這可能有用”
-
“模式說X,但我會以不同的方式對其進行調整”
-
“以下是主要問題:[列出未經調查的修復]”
-
在追蹤資料流之前提出解決方案
-
「再嘗試一次修復」(當已嘗試 2+ 次)
-
每次修復都會在不同的地方揭示新問題
**所有這些都意味著:停止。返回第一階段。 **
如果 3 個以上修復失敗: 質疑架構(請參閱階段4.5)
你的人類伴侶發出的信號表明你做錯了
注意這些重定向:
-
“那不是發生了嗎?” - 你假設沒有驗證
-
「它會告訴我們…嗎?」 - 你應該增加證據收集
-
「停止猜測」——你在不理解的情況下提出修復方案
-
「Ultrathink this」-質疑基本面,而不僅僅是症狀
-
「我們被困住了?」(沮喪)- 你的方法不起作用
當您看到這些時: 停止。返回第一階段。
常見的合理化理由
對不起 現實
「問題很簡單,不需要流程」 簡單的問題也有根本原因。對於簡單的錯誤,處理速度很快。
「緊急情況,沒有時間處理」 系統調試比猜測和檢查顛簸更快。
“先嘗試一下,然後再調查” 第一個修復設置了模式。從一開始就做對。
“確認修復有效後我將編寫測試” 未經測試的修復不會持續下去。首先測試證明這一點。
“一次進行多個修復可以節省時間” 無法隔離有效的方法。導致新的錯誤。
“參考資料太長,我會調整模式” 部分理解一定會出現錯誤。完整地閱讀它。
“我看到問題了,讓我解決它” 看到症狀≠瞭解根本原因。
「再嘗試一次修復」(兩次以上失敗後) 3+次失敗=架構問題。問題模式,不要再修復。
快速參考
相 主要活動 成功標準
1.根本原因 讀取錯誤、重現、檢查更改、收集證據 瞭解什麼和為什麼
2.圖案 查找工作示例,進行比較 找出差異
3.假設 形成理論,最少測試 證實的或新的假設
4.實施 創建測試、修復、驗證 錯誤已解決,測試通過
當流程顯示“沒有根本原因”時
如果系統調查顯示問題確實是環境性的、時間相關的或外部的:
-
您已完成該過程
-
記錄您調查的內容
-
實施適當的處理(重試、超時、錯誤消息)
-
添加監控/日誌記錄以供將來調查
但是: 95% 的「無根本原因」案例調查不完整。
配套技術
這些技術是系統調試的一部分,可以在此目錄中找到:
-
root-cause-tracing.md
-
透過呼叫堆疊向後追蹤錯誤以找到原始觸發器
-
defense-in-depth.md
-
在找到根本原因後添加多層驗證
-
condition-based-waiting.md
-
用條件輪詢替換任意逾時
相關技能:
-
superpowers:test-driven-development - 用於建立失敗的測試案例(第4階段,第1步)
-
超級能力:完成前驗證 - 在聲明成功之前驗證修復是否有效
現實世界的影響
從調試會話:
-
系統方法:15-30 分鐘修復
-
隨機修復方法:2-3小時的顛簸
-
首次修復率:95% vs 40%
-
引入新錯誤:接近零與常見