標籤: 系統接合

  • 舊系統整合場景下,會用 vs 不會用 Claude Code 的差距

    重點摘要

    • 舊系統整合最大的陷阱: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 確認影響範圍「找出所有隱性行為,不要開始設計」