舊系統接手與演進
在文件不完整、系統仍在運作的條件下,安全地理解、修改與延續服務
在文件不完整、系統仍在運作的條件下,安全地理解、修改與延續服務
Legacy 不等於「很舊」
- 已經承擔真實業務與使用者依賴
- 缺乏足夠測試、文件或可維護人員
- 技術、依賴或部署環境已經過時
- 修改成本與未知風險很高
- 沒有人能完整說明系統為什麼變成現在這樣
接手的第一個目標
不是立刻重寫
是建立可驗證的系統模型
先讓系統跑起來
- Repository、branch、tag 與實際部署版本
- Runtime、dependency、config、secret、data
- Build、startup、health check 與測試指令
- Local、test、staging、production 的差異
- 把成功與失敗步驟寫成可重複的 runbook
Repository Archaeology
- 入口點、目錄、module、service 與主要 dependency
- README、issue、PR、commit history、release note
- TODO、deprecated、feature flag 與 dead code
- 最常修改、最常出錯、最少測試的區域
- 找仍了解歷史的使用者、維運者與開發者
重建架構與資料流
使用者/排程/外部事件
→ 入口
→ 核心模組與規則
→ 資料庫/檔案/外部服務
→ 輸出、副作用與告警
每個結論要標示來自 Code、文件、歷史還是實際執行。
Characterization Test
- 不先宣稱舊行為正確,而是先固定「現在實際怎麼做」
- 選擇高價值輸入、輸出與副作用
- 建 golden master、snapshot 或 baseline dataset
- Bug 可能已被外部流程依賴,修改前要確認
- 測試提供安全網,讓後續重構可以比較前後差異
找出 Risk Hotspot
- 高修改頻率 × 高複雜度
- 核心資料、權限、公式與不可逆操作
- 沒有 owner、沒有監控、沒有回復方式
- 過時 dependency、單點服務與手工作業
- 每次修改都要碰很多無關模組的區域
小步重構
選一個小範圍
→ 建立 baseline test
→ 做一種結構改善
→ 執行測試與觀測
→ commit checkpoint
→ 再決定下一步
避免把重構、功能、升級與 migration 全混在一次大改。
Dependency Upgrade
- 先盤點直接與間接 dependency
- 讀 breaking change、migration guide、deprecation
- 一次升一個可控制範圍,保留 lockfile
- 建立相容性測試與 rollback point
- Runtime、OS、database、framework 可能需要分階段升級
Data Migration
- 盤點 schema、品質、容量與資料 owner
- Mapping、清理、backfill、驗證與 reconciliation
- Dual read/write、shadow traffic 或 parallel run
- Cutover 條件、停機窗口與 rollback plan
- 舊系統何時唯讀、封存與正式除役
Strangler Pattern 與漸進替換
既有系統
├─ 保留尚未替換的功能
└─ 將一小段流量導向新服務
↓
驗證後逐步擴大
用邊界逐步取代,避免一次 big-bang rewrite。
技術債與認知債
- 技術債:結構與工具造成未來修改成本
- 認知債:團隊不知道系統如何運作與為何如此
- 用 debt register 記錄影響、利息、風險與觸發條件
- 不是看到債就全部還,而是依未來修改與事故風險排序
- 文件、測試、觀測與 Git 歷史都能降低認知債
接手流程的產物
- System map、dependency inventory、data flow
- Build/run/deploy/rollback runbook
- Baseline test 與關鍵觀測點
- Risk hotspot、未知問題與技術債清單
- 小步修改計畫、owner 與驗收方式
看到 Agent 分析舊系統時
要區分它「從 Code 推論」與「已經實際執行驗證」的內容,
並要求指出檔案、symbol、test、log、trace 與 commit 證據。