安全地修改既有系統
已完成導入變更時,保留現有契約,並考慮舊用戶端、資料與部署順序。
檢查理解程度你在同一次發布中重新命名資料庫欄位,並更新應用程式。還可能出什麼問題?進行練習
學習目標
- 辨識局部程式碼變更可能影響的契約。
- 解釋分階段擴充再收縮的變更方式。
- 區分程式碼回復與資料復原。
找出變更周圍的契約
既有軟體有呼叫端、儲存資料、排程工作和維運程序。部分相依關係,無法從想編輯的檔案中看見。代理程式可能產生局部正確的變更,卻破壞其中一項契約。
實作前,找出受影響資料的讀取端與寫入端。檢查路由、背景工作、報表和外部整合,確認其他團隊或較舊用戶端版本,是否依賴目前行為。
請代理程式提供這份相依關係圖的證據。搜尋結果是有用起點,但動態呼叫和外部使用方,可能需要負責人確認。
讓目前行為可被觀察
對文件不足的模組,針對必須穩定的行為加入聚焦檢查。這些檢查描述目前契約,不代表所有既有行為都值得保留。
如果目前行為與需求衝突,記錄衝突。不要只因測試捕捉到某個資安缺陷,就保留它。取得必要決定,區分預期行為和缺陷。
使用貼近實際、但不含敏感資訊的測試資料。可能出現舊資料結構和不完整紀錄時,也應納入。新的資料結構描述若只用新建資料測試,可能掩蓋移轉問題。
審查版本間的過渡
以將 customer_name 改名為 display_name 的虛構情境為例。立即改名,可能在部署期間破壞舊應用程式執行個體。同一個 pull request 修改兩個檔案,不代表部署具有不可分割性。
分階段做法可以維持相容:
- 新增欄位,先不移除舊欄位。
- 定義新的寫入如何保持必要值一致。
- 使用可重新啟動的程序,補填既有紀錄。
- 驗證完整性與讀取端行為。
- 將讀取端移至新欄位。
- 只有所有使用方都不再依賴舊欄位時,才移除它。
具體方法取決於資料庫與寫入模式。如果其中一次寫入失敗,雙重寫入可能造成不一致。可能需要資料庫交易,或其他明確同步方式。檢查系統保證前,不要直接套用這個範例。
Martin Fowler 將這種一般過渡方式稱為 parallel change,也稱 expand-and-contract。核心是在移除前,先建立相容的過渡過程。
分開規劃復原與版本回復
程式碼回復會還原較早的應用程式版本,但不會自動撤銷資料移轉。舊版本可能無法理解新資料。破壞性移轉可能移除資訊,而回復程式碼無法找回這些資訊。
為每一步找出復原操作。可重新啟動的補填程序,可能能安全續行。錯誤轉換可能需要依保留的來源資料修正。破壞性操作則可能需要已驗證的還原程序。
確認誰負責復原決策,以及可能需要多久。不要把「我們有備份」當作復原符合服務要求的證據。
讓變更可供審查
將不相關清理與功能變更分開。在 pull request 提供相容計畫、驗證結果和移除條件,標出哪個步驟之後,回復需要額外工作。
代理程式能協助檢查使用方、準備移轉程式碼,但負責人仍須接受過渡與復原計畫。最終設計只是安全變更的一部分。
進行練習
選擇一項小型欄位或 API 變更。列出所有讀取端與寫入端,包括背景工作。描述先新增的步驟、過渡檢查及移除條件,並找出哪一步可能讓回復變得不可行。
下載工作表(Markdown)取消此選項,會刪除此瀏覽器儲存的所有進度。
進度只留在此瀏覽器。無須帳戶,沒有追蹤。