重點摘要
- 舊系統整合最大的陷阱:Claude 看不到舊系統,但舊系統的約束決定了新功能能不能用
- 不會用的人:讓 Claude 在沒有舊系統上下文的情況下做新功能,結果接不上去
- 會用的人:先讓 Claude 讀關鍵接口,CLAUDE.md 記錄現有約束,設計文件定義接合點
- 三個場景示範:醫療 HIS 接 LINE 掛號、舊報表接新數據、舊 ERP 接電商平台
上一篇文章講的是新功能開發。但現實是,大多數人面對的不是一張白紙,而是一個已經在跑的舊系統。
舊系統整合比全新開發難十倍,不是因為技術更難,而是因為有一大堆隱性約束 Claude 不知道。格式、命名、邊界、不能動的地方,這些都在舊代碼裡,Claude 看不到就無從遵守。
這篇用三個場景直接模擬:有舊系統在的情況下,會用和不會用 Claude Code 的差距。
根本差距:Claude 的上下文只有你給它的部分
Claude Code 非常聰明,但它只知道你告訴它的東西。在全新專案,你說什麼格式就用什麼格式,問題不大。在整合舊系統時,如果你沒有把舊系統的關鍵結構告訴它,它會做出一個邏輯正確但無法接上的東西。
這不是 Claude 的問題,是你的輸入不完整。
舊系統整合的核心挑戰是:讓 Claude 在動手之前,先理解它不能動的邊界在哪裡。
場景一:醫院 HIS 系統加掛 LINE 預約掛號
情境
一家地區醫院用了十年的 HIS 系統(Windows Server + MSSQL),所有掛號邏輯都在 stored procedures 裡。現在要加 LINE Chatbot 讓患者能線上預約,但 HIS 系統不能動,只能從外部透過 API 呼叫它。
不會用的人怎麼做
幫我寫一個 LINE Chatbot 預約掛號系統,要能讓患者選科別、選醫師、選時段。
Claude 做出一個完整的 LINE bot,資料庫設計清楚,對話流程順暢。
開始對接 HIS 系統時,問題一個接一個:
- HIS 的患者 ID 是 8 位數字,Claude 設計的是 UUID — 整個 primary key 要換
- HIS 的診次代碼格式是
YYYYMMDD-科別碼-序號(例如20260325-INT-001),Claude 自己設計了完全不同的格式 - HIS 只接受 stored procedure 呼叫,不開放直接讀表,Claude 設計的是直接 SELECT
- 科別代碼是 HIS 裡的維護資料(內科=INT、外科=SUR),Claude 用了自己的命名
每一個問題單獨看都能修,但修完之後發現下一個格式又不對。最後花了兩天在做格式轉換,而不是做功能。
結果:開發 3 天,對接 2 天,還有格式轉換層要長期維護。
會用的人怎麼做
第一步:先讓 Claude 讀懂舊系統的接口
把 HIS 系統對外開放的 SP 簽名整理成文件,餵給 Claude:
請先閱讀以下 HIS 系統的接口文件,
告訴我你對這個系統的理解,特別是資料格式和呼叫限制,
再討論 LINE bot 的架構設計。
--- HIS 接口文件 ---
sp_GetAvailableSessions
@DeptCode NCHAR(3) -- 科別碼,參照 tb_Dept.DeptCode
@DateFrom NCHAR(8) -- YYYYMMDD 格式
@DateTo NCHAR(8)
回傳: SessionId NCHAR(16), DoctorName, SessionDate, RemainSlots
sp_CreateBooking
@PatientId NCHAR(8) -- 8位數字,不足補0
@SessionId NCHAR(16) -- 從 sp_GetAvailableSessions 取得
@Phone NVARCHAR(20)
回傳: BookingNo NCHAR(12), Status (SUCCESS/FULL/DUPLICATE)
sp_CancelBooking
@BookingNo NCHAR(12)
@Reason NVARCHAR(100)
---
第二步:CLAUDE.md 記錄現有系統的約束
## 整合約束(HIS 系統,不可更動)
- PatientId:8 位數字字串,不足補 0(例如 "00012345")
- SessionId:格式為 YYYYMMDD-DeptCode-NNN(例如 "20260325-INT-001")
- 所有 HIS 呼叫只能透過 stored procedure,不允許直接查表
- 科別代碼參照 tb_Dept,常用:INT=內科、SUR=外科、PED=小兒科
## 新系統原則
- LINE bot 層只做對話邏輯
- HIS 接口層做格式轉換(HisAdapter class)
- 不在 LINE bot 層直接呼叫 HIS
第三步:設計文件定義接合點,不是重新設計格式
# 功能:LINE 掛號 → HIS 預約對接
## 接合點(Integration Points)
LINE 用戶選擇診次 → HisAdapter.getAvailableSessions(deptCode, dateRange)
→ 呼叫 sp_GetAvailableSessions
→ 回傳格式轉為 LINE flex message 可用的結構
用戶確認掛號 → HisAdapter.createBooking(lineUserId, sessionId, phone)
→ 查詢或建立患者檔(PatientId)
→ 呼叫 sp_CreateBooking
→ 處理 FULL / DUPLICATE 回傳狀態
## 不碰的東西
- HIS 資料庫 schema 完全不動
- 所有 PatientId 維持 8 位補零格式
- SessionId 格式完全繼承 HIS
## Done When
- HisAdapter 有完整的 unit test(mock SP 回傳)
- LINE bot 不包含任何 HIS 格式邏輯(全在 Adapter)
結果:1.5 天完成,無格式轉換層,後續維護只在 HisAdapter 這一層。
場景二:舊版股市報表腳本接新即時數據
情境
一個量化分析師用了三年的 Python 腳本,每天手動下載 CSV,跑一堆計算,輸出報表。現在要改成自動化:自動爬取數據、自動計算、推播到 Line Notify。但舊腳本的計算邏輯非常複雜(含自訂指標、過去三年調整過的參數),不能改,只能把數據來源換掉。
不會用的人怎麼做
幫我把這個股市分析腳本改成自動化,自動抓數據然後推 LINE 通知。
Claude 看了舊腳本,做了一個新的自動化版本。看起來很整齊,比舊腳本乾淨很多。
跑了一週,發現結果跟舊版不一樣:
- 舊腳本的 RSI 計算用的是 Wilder 平滑法,Claude 預設用了 SMA 版本,數值不同
- 舊腳本對成交量有一個「過去 20 日剔除最高最低各兩天後的平均」的自訂邏輯,新版沒有
- 舊腳本在除權息日前後有特別處理,新版沒有
- 欄位名稱被 Claude 重新命名了(舊版
vol_adj在新版變成adjusted_volume),下游所有 Excel 公式全壞
分析師說:「它幫我重寫了,但重寫出來的東西跟我的不一樣,我現在不知道以哪個為準。」
結果:新舊結果不一致,花了一週在驗算差異,反而比手動下載多花時間。
會用的人怎麼做
關鍵原則:計算邏輯一行都不能動,只換數據來源。
第一步:讓 Claude 讀懂舊腳本,先提取它的業務邏輯
請閱讀這個舊腳本,告訴我:
1. 它依賴哪些輸入欄位(欄位名稱和格式)
2. 有哪些自訂計算邏輯(非標準指標)
3. 最後輸出哪些欄位
不要修改任何東西,只告訴我你的理解。
這一步讓 Claude 自己找出所有隱性依賴,避免後面遺漏。
第二步:CLAUDE.md 把舊腳本的約束凍結
## 舊系統相容性約束(不可更動)
- 所有輸出欄位名稱必須與 legacy_report.py 完全一致
(vol_adj、rsi_wilder、price_adj 等,不得重新命名)
- RSI 計算必須使用 Wilder 平滑法(非 SMA),與舊版等價
- 成交量平均:去掉最高最低各 2 天後的 16 日均量
- 除權息調整邏輯:參見 legacy_report.py 第 87-134 行,禁止修改
## 本次修改範圍
- 只修改數據來源層(DataFetcher class)
- 所有計算邏輯保持不變
- 輸出格式和欄位名稱保持不變
第三步:設計文件只描述「換什麼」,明確說「不換什麼」
# 功能:數據來源自動化
## 要換的
舊:手動下載 CSV 放在 ./data/ 目錄
新:DataFetcher 自動從 TWSE API 抓取,存成相同格式的 DataFrame
## 不換的
- 所有 calculate_*() 函數:一行都不動
- 所有欄位名稱
- 輸出的 Excel 格式和公式
## 驗證方式
用同一天的歷史數據,新舊兩版並排執行,
所有欄位數值差異必須在浮點誤差範圍內(< 0.0001)
「驗證方式」這一段給了 Claude 一個清楚的完成定義:不是「看起來跑得動」,而是「跟舊版數字一樣」。
結果:1 天完成,新舊並排驗算通過,分析師信心十足上線。
場景三:舊訂單系統接新電商平台(Shopee / momo)
情境
一家中型品牌商有自己的後台訂單系統(自建,PHP + MySQL,跑了七年),現在要同時開 Shopee 和 momo 的店,訂單要自動回拋到自建系統,庫存要即時同步。自建系統的代碼文件不齊全,但不能大改,只能在外面包一層。
不會用的人怎麼做
幫我串接 Shopee 和 momo 的訂單,自動同步到我們自己的系統。
Claude 寫了一個整合服務,讀 Shopee/momo 的 webhook,轉換格式,打進自建系統的 API。
測試時發現:
- 自建系統的商品 SKU 格式是
PRD-XXXXXXXX,但 Shopee 上的 SKU 是當初手動輸入的,有些根本對不上 - 自建系統的訂單狀態只有 5 種,Shopee 有 12 種,Claude 的對照表做了一半,有幾個狀態沒處理
- momo 的訂單金額包含平台折扣,自建系統的商品價格是定價,兩邊金額對不上帳
- 自建系統在創建訂單時會觸發一個庫存扣減的觸發器,Claude 不知道這件事,導致庫存被扣兩次
最後一個問題最嚴重:庫存被扣兩次,一直到實際出貨才發現。
結果:開發 4 天,測試又 3 天,上線後還是出現庫存問題。
會用的人怎麼做
舊系統不熟,先讓 Claude 幫你挖清楚它的邊界。
第一步:讓 Claude 讀舊系統,主動找隱性行為
請閱讀這個訂單系統的代碼,特別注意:
1. 創建訂單時會觸發哪些副作用(觸發器、事件、其他表的更新)
2. 庫存扣減在哪裡發生(是 API 層還是資料庫層)
3. 訂單狀態的完整清單和流轉規則
告訴我所有你發現的隱性行為,不要開始寫任何代碼。
「隱性行為」這個說法很重要。Claude 在讀舊代碼時會主動找資料庫 trigger、事件監聽器、side effect,這些是最容易被遺漏的整合風險。
第二步:用 Plan Mode 規劃整合架構,重點在「邊界」
【背景】
自建訂單系統(PHP + MySQL),創建訂單時資料庫層會自動扣減庫存(trigger)。
Shopee 和 momo 各有自己的訂單狀態體系。
【目標】
Shopee/momo 新訂單自動進到自建系統,庫存只扣一次,狀態對照完整。
【約束條件】
- 自建系統的 trigger 不能改(沒有完整文件,風險太高)
- SKU 對照表需要人工確認後再上線(不能用 Claude 猜測)
- momo 的折扣金額要分開記錄,不能直接入自建系統的商品價
請制定整合架構計劃,
特別說明如何避免庫存被扣兩次,
等我確認計劃後再開始實作。
Plan Mode 裡,Claude 提出了三個方案,推薦的是:新建一個 OrderBridge 服務,只負責格式轉換和狀態對照,在呼叫自建系統 API 之前先把庫存檢查做在 Bridge 層(避免 API 呼叫失敗後 trigger 已執行的問題)。
第三步:設計文件把 SKU 對照、狀態對照、金額拆分全部定義清楚
## SKU 對照策略
- 對照表存在 sku_mapping 資料表,人工審核後才生效
- 找不到對照的 SKU:訂單進 pending_review 佇列,不自動處理
- 禁止猜測或模糊匹配
## 訂單狀態對照(Shopee → 自建)
UNPAID → 不同步(等付款)
READY_TO_SHIP → processing
SHIPPED → shipped
COMPLETED → completed
CANCELLED → cancelled
其他狀態 → 記錄 log,不同步,發警報
## momo 金額處理
momo_original_price → 自建系統 unit_price
momo_discount → 另存 discount_record 資料表
momo_final_price → 自建系統 actual_amount
(三個欄位分開記錄,不做合併計算)
結果:2 天完成 OrderBridge,庫存零重複扣減,SKU 對照人工審核後上線,穩定運行。
舊系統整合的核心技巧整理
| 技巧 | 怎麼做 | 目的 |
|---|---|---|
| 先讓 Claude 讀現有接口 | 提供 API 簽名、schema、關鍵函數,要求 Claude 說出理解後再動手 | 讓 Claude 在正確的上下文下設計,不做無效假設 |
| 要求 Claude 找隱性行為 | 明確說「找出所有 trigger、side effect、副作用,不要開始寫代碼」 | 在整合前把地雷挖出來,不是做完才踩到 |
| CLAUDE.md 凍結不能動的邊界 | 在 CLAUDE.md 明確寫「不得修改 X 格式 / Y 欄位名稱 / Z 計算邏輯」 | Claude 不會因為「更整齊」而擅自重新命名或重構 |
| 設計文件定義接合點,不定義格式 | 設計文件描述「新舊系統在哪裡接觸」,格式繼承舊系統,不重新設計 | 避免做一個格式轉換層長期維護 |
| 驗證方式要對比舊系統 | Done When 裡明確說「與舊系統同樣輸入,輸出結果必須一致」 | 讓 Claude 自己驗算新舊等價性,不是跑起來就算完成 |
一個可以直接用的提示模板
每次要在舊系統上加新功能,用這個模板啟動:
【現有系統】
[描述現有系統的技術棧和關鍵接口,附上接口文件或關鍵代碼片段]
【要加的功能】
[一句話描述]
【不能動的邊界】
- [現有系統的格式、欄位名稱、計算邏輯等不能更動的項目]
- [如果有 DB trigger 或其他隱性行為,也列在這裡]
【請先做這兩件事,再開始設計】
1. 告訴我你對現有接口的理解(特別是你覺得可能影響整合的部分)
2. 指出你看到的整合風險(格式衝突、重複操作、狀態對照缺口)
確認理解正確後,我們再討論設計。
這個模板做了三件事:把舊系統的上下文給 Claude、凍結不能動的邊界、要求 Claude 在動手前先說出它的理解和風險判斷。
常見問題
Q:舊系統的代碼很亂,文件也沒有,怎麼辦?
先讓 Claude 讀代碼,問它「這個系統對外暴露了哪些接口?資料庫有哪些關鍵的 table 和 trigger?」讓 Claude 幫你反向整理出一份接口文件,確認沒有遺漏後再進行整合設計。不要跳過這一步,這是整合成功的前提。
Q:整合的範圍不確定,不知道要動到哪裡?
先用 Plan Mode,給 Claude 目標和約束,讓它畫出影響範圍。Plan Mode 的價值在複雜整合場景特別高,因為它會列出所有相關的文件和狀態流,讓你確認範圍是否正確,再決定怎麼切入。
Q:新功能做完,但舊系統有些邏輯說不清楚,怕 Claude 做錯?
這種情況用「新舊並排驗算」:先在測試環境讓舊版和新版用同樣輸入各跑一次,比較輸出。在設計文件裡明確寫出這個驗證條件,Claude 就會把「新舊等價」列為完成定義的一部分。
從不會用到會用:舊系統整合的具體升級路徑
舊系統整合的升級路徑跟全新開發不太一樣:問題不是「我沒說邊界條件」,而是「Claude 根本不知道舊系統長什麼樣」。所以升級的重點是:在動手前把舊系統的關鍵資訊餵給 Claude。
第一步:今天就能做到(一個句子)
在你的提示前面加上這段:
我有一個現有系統,新功能必須跟它相容。
現有系統的關鍵格式:
[把你知道的接口格式、欄位名稱、資料格式貼在這裡]
新功能不能更動上面這些格式。先告訴我你的理解,再開始設計。
就算你只知道一部分格式,先寫一部分。有比沒有好。
醫療 HIS 整合:Level 0 → Level 1
| 不會用(Level 0) | 初步會用(Level 1) |
|---|---|
| 幫我串接 HIS 系統做 LINE 掛號 | (見下方) |
我有一個舊的 HIS 系統(不能修改),需要在外面接一個 LINE 掛號 bot。
HIS 現有接口(Stored Procedure):
sp_GetAvailableSessions(@DeptCode NCHAR(3), @DateFrom NCHAR(8), @DateTo NCHAR(8))
sp_CreateBooking(@PatientId NCHAR(8), @SessionId NCHAR(16), @Phone NVARCHAR(20))
回傳 Status: SUCCESS / FULL / DUPLICATE
格式約束(不能改):
- PatientId 是 8 位數字字串,不足補 0
- 所有呼叫只能透過 stored procedure,不能直接查表
請先告訴我:
1. 你對這個 HIS 接口的理解
2. 你覺得 LINE bot 和 HIS 之間需要什麼樣的轉換層
確認後再討論架構設計。
舊報表腳本接新數據:Level 0 → Level 1
我有一個舊的 Python 分析腳本,計算邏輯不能動,只要換掉數據來源(從手動 CSV 改成自動抓取)。
舊腳本的輸入依賴(這些欄位名稱不能改):
- date (YYYY-MM-DD)
- open, high, low, close, volume
- vol_adj(自訂欄位:去掉最高最低各2天的16日均量)
計算邏輯不能動的原因:
- RSI 用的是 Wilder 平滑法(非標準 SMA),三年來的報告都是這個版本
- 改了數值會跟歷史記錄不一致
請先告訴我:
1. 你理解哪些東西不能動
2. 你打算怎麼讓新舊版本在同樣輸入下輸出一致的結果
確認後再開始實作數據來源層。
舊 ERP 接電商平台:Level 0 → Level 1
我有一個舊的訂單系統(PHP + MySQL),要串接 Shopee 的訂單進來。
舊系統不能大改,只能在外面包一層。
已知的舊系統行為:
- 創建訂單時,資料庫層有 trigger 會自動扣庫存
- 訂單狀態:pending / processing / shipped / completed / cancelled(只有這五種)
Shopee 訂單狀態有 12 種,需要做對照。
我擔心的問題:
- 庫存被扣兩次(trigger + 外面的 API 都扣)
- 狀態對照不完整,有些 Shopee 狀態沒有對應的舊系統狀態
請先幫我分析這兩個風險,告訴我你的處理方案,再開始設計架構。
注意最後一段:把你擔心的問題說出來。這讓 Claude 優先處理你知道有風險的地方,而不是從它認為重要的地方開始。
第二步:下週可以做到(CLAUDE.md 記錄舊系統約束)
舊系統整合的 CLAUDE.md 要特別加一個「整合約束」區塊:
# 整合約束(現有系統,不可更動)
## [系統名稱] 的格式規範
- [欄位名稱] 的格式:[說明]
- [接口規範]:[說明]
- 禁止直接操作資料庫,只能透過 [API / SP / 特定方法]
## 已知的隱性行為
- [觸發器 / 事件 / side effect 描述]
- 注意:[操作 X] 會同時觸發 [Y],不要重複執行
## 新功能的邊界
- 只修改 [Adapter / Bridge / 特定模組],不動舊系統
- 欄位名稱繼承舊系統,不重新命名
每次發現一個新的隱性行為(觸發器、計算邏輯、格式特例),就加進這個區塊。它會越來越完整,讓你以後的整合工作越來越省力。
第三步:一個月後的進化
進化 A:在開始任何整合前,先讓 Claude 找隱性行為
請閱讀 [現有系統代碼/文件],找出所有:
1. 資料庫 trigger 和它的作用
2. 創建/更新/刪除記錄時的 side effect
3. 對外暴露的接口(API / SP / 事件)和它們的格式
告訴我你找到的所有隱性行為,不要開始設計,先讓我確認。
這個步驟在整合開始前把地雷挖出來,比做完後踩到省 10 倍時間。
進化 B:複雜整合用 Plan Mode,重點讓 Claude 畫出影響範圍
【現有系統】[描述]
【目標】[一句話]
【不能動的邊界】[列清楚]
請制定整合計劃,特別標出:
- 會影響到的現有功能
- 每個整合點的風險
- 我需要在上線前人工驗證的項目
等我確認計劃後再開始實作。
進化 C:設計文件加「新舊等價性驗證」
舊系統整合的完成定義,永遠要加這一條:
## 驗證方式
用同一份歷史輸入,新舊兩版並排執行,
[關鍵輸出欄位] 的結果差異必須在 [可接受範圍] 內。
新版上線前,提供新舊對比報告。
| 階段 | 做什麼 | 關鍵句 |
|---|---|---|
| Level 0 | 直接說要串接什麼 | — |
| Level 1(今天) | 把舊系統格式和約束說清楚 | 「這些格式不能改,告訴我你的理解再開始」 |
| Level 2(下週) | CLAUDE.md 記錄舊系統約束和隱性行為 | 每次整合後補一條「已知隱性行為」 |
| Level 3(一個月後) | 先讓 Claude 挖地雷,再 Plan Mode 確認影響範圍 | 「找出所有隱性行為,不要開始設計」 |
發佈留言