重構 —— 一次結構性實驗
重構在保持可觀察行為不變的前提下,改變程式結構。它執行一次由呼叫者選擇的轉換,並報告結果。
提示詞
重構 billing-service/internal/retry/backoff.go:將 RetryRequest 中的指數退避計算提取到一個獨立的函式中,不做任何其他行為變更。記錄基準線,在變更前後執行 go test ./internal/retry/...,並回報 diff 摘要、指令、結果以及任何未檢查的事項。
成功條件
- 報告中應指明被保留的行為,並引用在變更前後皆已執行的
go test ./internal/retry/...。 git diff --stat僅觸及internal/retry/backoff.go,絕不碰觸無關的檔案。- 每當被變更的程式面產生輸出時,例如在變更前後使用
sha256sum,應擷取金鑰輸出(golden-output)的雜湊值並以位元組為單位進行比較。 - 報告中的「未檢查行為」清單必須在輸出中呈現,即使清單為空,也需列出所有被閘門跳過的程式面露面範圍。
流程
- 指定被保留的行為、有焦點的驗收面,以及其呼叫者所面對的具體結構問題。重複使用呼叫者的領域術語和已被接受的運作範例;在變更過程中保持其意義不變。
- 記錄一份誠實的基準線,包括任何可重現的環境性失敗。對於比較可執行行為的評估,請在編輯前鎖定起始原始碼並建構其基準線;保留該二進位檔與比較用的輸入。使用這些輸入和相同的工具鏈來比較候選版本。此舉不會為一般重構增加任何可執行比較的儀式。
- 應用一次有邊界的轉換:提取、重新命名、內聯、簡化、封裝、移動或刪除死碼。根據呼叫者必須理解的內容以及必須修改領域規則的位置來判斷結果,而非僅依據檔案大小。
- 執行有焦點的檢查,以及基於受變更面積而合理的最小套件級回歸測試。
- 回報 diff 摘要、指令、結果以及未檢查的行為。
請勿將新發現的行為修正與結構性變更混為一談。紅色的結果是提供給呼叫者的證據;此技能不會自動進行還原、縮小範圍、重試、提交、驗證或安排後續工作。
職責與介面成本
在新增介面或拆分模組之前,請檢查代表性的呼叫者。計算他們需要協調的概念數量:必要的設定、順序、狀態、錯誤處理以及重複的領域規則。一個有用的邊界將一個內聚的規則置於單一擁有者之下,並讓呼叫者能夠要求一個結果,而無需重現該規則。拒絕任何僅新增另一個名稱或將相同的協調工作推給其呼叫者的包裝函式。當沒有任何具體的呼叫者問題需要變更現有邊界時,現有邊界就已足夠。
對提取的運算與型別,使用呼叫者的詞彙。會改變行為的命名模糊性,應歸屬於既有的領域定義;僅在該區別需要處理時,才諮詢領域。重新命名公開符號、持久化欄位或協定值屬於相容性變更,除非被接受的範圍已另有規定。
當轉換需要一個接縫(seam)——一個提取邊界、介面或模組拆分——且存在一個以上的候選接縫時,請在實際切開之前先進行探測。在可拋棄的隔離環境中(一個呼叫者政策允許的草稿分支、工作目錄或複製的目錄樹)執行探測:粗略地建立接縫,觀察它帶來的影響——簽章變更、匯入循環、測試重寫——然後丟棄探測內容,僅保留知識。停止條件:最多進行兩次探測;如果第二個候選接縫也遭遇阻力,請將兩個發現結果一併回報給呼叫者,而不是嘗試第三個。直接在工作目錄裡切開第一個想得到的接縫,是過早接縫的失敗模式:錯誤的邊界會因為現在恢復它的成本比忍受它更高而變得僵化。
中立性閘門
「行為守恆」是一個需要執行的聲明,而非一個無需驗證的主張。以下列行為相同的證明來把關轉換:
- 有焦點的檢查與套件級回歸測試在變更前後都必須通過,且具有相同的一組預先存在的失敗——不能有新的紅燈,也不能有悄然消失的紅燈(一個停止執行的測試本身就是一種行為變更)。
- 對於產生輸出的程式面(生成器、序列化器、格式化器、報告),請對輸出進行雜湊處理:在變更前,針對相同的輸入擷取金鑰輸出雜湊值,並在變更後以位元組為單位進行比對。雜湊值不符是一個需要提出並解釋的行為差異,絕不能聳肩帶過;由呼叫者決定是要保留、縮小範圍還是還原變更。
- 在受變更的程式面上,可觀察的錯誤訊息、結束代碼和公開簽章,都是行為的一部分,除非呼叫者將其排除在外。
在事後被跳過或縮小範圍的中立性閘門,是事後中立性的失敗模式——diff 內容決定了什麼被測試。請在報告的「未檢查行為」清單中,列出任何閘門未覆蓋到的程式面露面範圍。