以前還有幾個老 COBOL 程式設計師懂這套系統,用 AI 遷移到 Java 後反而沒人能接手了

一批研究 COBOL 程式碼遷移的工程師發表了論文,提出把 AI 鎖進籠子。

圖片

論文標題很樸素:《Agentic Method for Deterministic Validation of Legacy Code Migration》。他們設計了一個叫 Locksmith Loop 的系統——名字取得精準,「鎖匠」,不是「大師」。不指望 AI 一次把活幹好,要的是把 AI 限制在一個確定性的框架裡,讓它只做它擅長的事。

但真正有意思的不是這個結論。是他們為什麼不得不這樣做,以及這樣做之後發生了什麼

三個模組,AI 只碰一個

Locksmith Loop 的架構分三層。

第一層是 Migrator。COBOL 原始碼進來,Java 目標程式碼出去。這一步不用 LLM,用的是確定性 AST 轉換器——規則寫死,COMPUTEBigDecimal.add()PERFORM VARYINGfor 迴圈。每次跑,每次結果一樣。TimByte 在 HN 上總結得精準:「他們把程式碼生成委託給確定性工具,模型只做輸入 fuzzing——讓它跟資料搏鬥,別碰語法。」

第二層是 Witness Search。這是 AI 唯一出場的地方。LLM 不斷構造輸入案例,企圖穿透程式的所有分支。每次跑完,覆蓋率分析器會檢查哪些分支還沒被觸達,然後 LLM 針對性地構造新輸入。這個過程循環往復,直到覆蓋率推不動為止。

第三層是 Oracle。COBOL 原版和 Java 遷移版同時跑同一個輸入,輸出必須逐位元一致。任何偏差都視為遷移失敗,回退修正。

為什麼要這樣設計?因為每一步都有明確的失敗模式。

圖片

Migrator 是確定性的,所以翻譯錯誤是可重現的、可追溯的。如果 COMPUTEBigDecimal 的精度出了問題,你會知道是轉換規則寫錯了,不是模型在某次推理中機率偏移了。

Oracle 是確定性的,所以驗證結果是二元的——對就是對,錯就是錯。不存在「看起來差不多」的灰色地帶。

Witness Search 是唯一非確定性的環節。但它的失敗模式是可控的——最壞情況是沒找到某個分支的觸發輸入,導致覆蓋率不夠。它不會產生錯誤程式碼,不會引入幻覺,不會在翻譯環節製造 bug。

這就是 Locksmith 的設計哲學:把 AI 放在它失敗後果最輕的地方。

當 AI 推不動了

Witness Search 不是萬能的。跑到某個分支邊界時,它可能會卡住。論文裡管這種情況叫 Locked Paragraph——一個阻止深入探索的條件,AI 構造不出能穿透它的輸入。

圖片

這是「鎖匠」名字的另一層含義:系統不指望 AI 能打開所有鎖。當 AI 推不動時,分析器會標記這個 Locked Paragraph,然後系統繼續推進其他分支。最終覆蓋率取決於 AI 能找到多少「鑰匙」。

論文報告了三個測試案例的結果。兩個開源 COBOL 程式,一個「內部生產級」程式。規模從 430 行到 4114 行。兩個開源程式達到了「幾乎完全覆蓋」。生產級程式達到了 91.90% 的分支覆蓋率。

91.90%。這個數字本身沒有太多討論價值,因為樣本太小。真正有價值的是剩下那 8.1% 意味著什麼。Locked Paragraph 是 AI 能力的邊界——它找到了 91.90% 的鑰匙,剩下 8.1% 的鎖它打不開。這些鎖在真實系統裡,很可能對應著最複雜的業務邏輯、最深的巢狀條件、最古老的 corner case。

連 bug 一起搬,是設計目標

架構還有一個反直覺的設計:遷移後的 Java 必須和原 COBOL 行為完全一致,包括 bug

aldente0630 在 Hacker News 上澄清了這一點:「保留 bug 是明確的設計目標。」但這不意味著論文在鼓勵保留 bug——它只是承認了一個現實:在 legacy 遷移的世界裡,這叫 bug-for-bug compatibility。那些 bug 已經在生產環境跑了二十年,下游系統依賴它們的行為。修了一個 bug,等於修了一個「別人以為正常」的功能。

Hyrum's Law 在這裡完全適用:「對於有足夠多使用者的系統,任何可被觀察到的行為——無論規範裡寫了還是沒寫——都會有人依賴它。」

但 bug-for-bug 有一個前提:Oracle 對比的是行為,不是程式碼。你保留了 bug 的行為,但你沒有保留 bug 的可理解性。原來的 COBOL 老程式設計師知道那個 bug 為什麼存在——可能是某次緊急修復留下的,可能是某個業務規則變更的遺跡。但 Java 程式設計師看到這段「故意保留 bug 行為」的程式碼時,他們只會看到一段看起來像是寫錯了的程式碼,沒有任何上下文。

4KLOC 和 230KLOC

Hacker News 上的評論沒有討論架構設計,而是直接質疑了論文的規模。

pacaro 給出了真實世界的尺度:「IRS(美國國稅局)一家就有大約 160 個 COBOL 程式,平均每個 23 萬行程式碼。」

fock 的評論更具體,因為他試過:「我們用的程式碼裡內嵌組語,跨十幾個檔案、5 萬行。這個程式用了某個預處理器,我們測試的所有 LLM 完全不知道它是什麼——它們會編造它的功能。Gemini 2.5 甚至沒注意到有預處理器存在。」

這指向了 Locksmith Loop 的真正邊界。Migrator 是確定性 AST 轉換器,但 AST 轉換的前提是你能 parse 原始碼。如果原始碼裡有預處理器巨集、內嵌組語、CICS 事務指令、JCL 批次處理調度——這些不是 COBOL 語法的一部分,是環境的一部分。AST 轉換器不認識它們,也不會編造它們(這是優點),但它會直接失敗(這是問題)。

Zenst 補充了精度問題:「COBOL 以固定無捨入數學聞名。Java 的 0.1 + 0.2 等於 0.30000000000000004。除非全面使用 BigDecimal,否則遷移從一開始就是壞的。」論文用了 BigDecimal,這是對的。但金融系統的 COBOL 程式通常使用 packed-decimal(BCD 編碼),其精度和捨入行為與 BigDecimal 並不完全等價。Oracle 的逐位元對比會抓住這些差異,但修復它們意味著在 Migrator 裡寫越來越複雜的規則。

換句話說,Locksmith Loop 的確定性架構方向是對的,但它的工程複雜度會隨系統規模非線性增長。從 4KLOC 到 40KLOC,不是工作量乘以 10,是你要處理的邊緣案例、環境依賴、精度差異、非標準語法全部同時爆炸。

COBOL-in-Java

dragonwriter 在 HN 上點出了這個架構最深層的矛盾:「唯一現實的低錯誤率方案不是更複雜的 AI 用法,而是確定性轉譯。問題在於,這樣得到的是 COBOL-in-Java——跑起來正確,但維護起來是惡夢。」

確定性轉換的產物是:語法是 Java,靈魂是 COBOL。變數名、控制流、資料結構全部帶著 1960 年代的味道。PERFORM VARYING 變成了 for 迴圈,但變數的命名方式、資料的組織邏輯、錯誤處理的分支結構,全部原樣保留。

人類程式設計師做遷移時,會做一件 Migrator 不會做的事:重新理解系統的意圖,然後用新語言的慣用方式重新表達。這引入了風險(理解可能出錯),但這是唯一能產出可維護程式碼的方式。

Migrator 選擇了零風險路徑,但付出了可維護性的代價。你失去了 COBOL 老程式設計師,換來了 Java 程式設計師——他們看著這套程式碼,比老程式設計師還困惑。

matsemann 在 HN 上的第一句話就是這個意思:「以前至少還有幾個 COBOL 老程式設計師懂這套系統。現在沒人懂了。」你把一套沒人懂的老系統,變成了一套沒人懂的新系統。問題沒有解決,只是換了個語言。

論文沒說的東西

Locksmith Loop 的架構設計是對的。把 AI 限制在測試生成,把翻譯和驗證留給確定性程式碼——這可能是 AI 在嚴肅軟體工程中唯一可靠的使用方式。

但它迴避了一個更大的問題:遷移 COBOL 系統的真正瓶頸從來不是「翻譯一段程式碼」,而是理解這個系統在做什麼。二十年沒人碰過的程式碼,沒有文件,沒有測試,原開發者已退休。你連它應該產生什麼輸出都不知道,你怎麼驗證 Oracle 的輸出是對的?

論文假設 Oracle 是給定的——COBOL 原版能跑,能產生輸出,用來和 Java 版對比。但在真實場景裡,COBOL 系統可能已經跑不起來了,或者只能在一個無法複製的特定大型主機環境裡跑。Oracle 不是現成的,Oracle 本身就是一個需要重建的東西。

這不是 Locksmith Loop 的錯。這是一個驗證方法論文,不是遷移工程論文。但如果你正在認真考慮遷移 COBOL 系統,你需要知道的不是「AI 能做測試生成」,而是「你的 COBOL 程式還能跑嗎?」

參考來源

相關文章推薦

分享網址
AINews·AI 新聞聚合平台
© 2026 AINews. All rights reserved.