# 有損算子與重寫決策：編譯不對稱性的認識論觀察

**EveMissLab 實驗站筆記**
**作者：Neo.K（許筌崴）**
**日期：2026年6月**

---

## 一、觀察的起點

在一次 Rust 專案的除錯過程中，一個看似平凡的問題觸發了更深的思考：為什麼反編譯在技術上如此困難，而編譯卻相對直接？這個不對稱性不只是工程細節，它指向的是一個更根本的認識論問題——信息在變換過程中的不可逆損失。

本文從這個具體觀察出發，嘗試建立一個連貫的認識框架，最終觸及 AI 時代軟體工程中「重寫 vs. 維護」的決策邏輯。

---

## 二、編譯作為有損變換

以 Rust 的 `--release` 編譯模式為例，編譯器在將原始碼轉換為機器碼的過程中，系統性地摧毀了以下幾類信息：

**符號信息**：變數名稱（`frontier`、`came_from`）、函式名稱（`solve_parallel`）、注釋與文件字串，全部在編譯後消失，替換為暫存器編號與記憶體位址。

**結構信息**：函式邊界往往消失。積極的內聯優化（inlining）將多個函式合併為單一指令序列；迴圈展開（loop unrolling）將顯式的迭代結構平鋪成線性指令流。

**類型信息**：高階類型系統（所有權、借用、泛型參數）在編譯後退化為原始位元組操作。`Vec<(i32, i32)>` 與 `Vec<f64>` 在 binary 層面的差異，只剩下位元組寬度。

**意圖信息**：最難恢復的是「為什麼這樣寫」。程式設計師的設計決策、演算法的選擇理由、特定邊界條件的處理邏輯——這些在任何編譯層面都不存在對應的表示。

從信息論的角度來看 [Shannon, 1948]，編譯是一個高度不均衡的變換：它保留了計算語義（程式的輸入輸出行為），但大量摧毀了符號語義（人類可讀的意圖表示）。這兩種語義並不等價，而編譯器的優化目標明確地選擇了前者。

---

## 三、反編譯的病態性

反編譯的根本困難在於它面對的是一個**病態問題（ill-posed problem）**。

一個問題被稱為病態，是指其解不存在唯一解，或對輸入的微小擾動產生巨大的輸出變化。反編譯符合第一個條件：給定一份 binary，存在無限多份原始碼都能編譯到相同（或等價）的機器指令。

具體說：

- 同一段排序邏輯，可能有數十種等價的寫法。
- 不同的變數命名（`i` vs. `index` vs. `cursor`）產生完全相同的 binary。
- 函式是否內聯、迴圈是否展開，這些編譯器決策在 binary 層面是不可逆的。

反編譯器（如 Ghidra、IDA Pro）的工作本質上是**在無限多個可能解中選擇一個「最合理」的近似**，這依賴啟發式規則、模式匹配、以及對常見代碼模式的統計知識。它輸出的不是原始碼，而是「一份能產生相同行為的可能原始碼」。

這個不對稱性揭示了一個更廣泛的原則：**凡是有損的正向變換，其逆變換必然是病態的**。JPEG 壓縮如此，雜湊函式如此，編譯亦如此。

---

## 四、傳統智慧：不要重寫

軟體工程中有一條流傳甚廣的戒律。2000 年，Joel Spolsky 在其文章《Things You Should Never Do, Part I》中提出，從頭重寫是軟體工程師可能犯下的最嚴重錯誤 [Spolsky, 2000]。其論據是：

> 舊的、混亂的代碼中包含了大量隱性知識——數年的 bug fix、對邊界條件的處理、對使用者行為的適應。這些知識不在注釋裡，不在文件裡，它們**就是代碼本身**。

這個論點在本質上是說：遺留代碼是一個**有損壓縮的知識庫**，雖然表示形式（代碼品質）惡化了，但壓縮進去的內容（領域知識）仍然存在。重寫等同於扔掉這份知識庫，從零開始重新積累。

Ward Cunningham 後來用「技術債」這個概念來量化這種知識積累的代價 [Cunningham, 1992]：你今天寫的每一行糟糕的代碼，都是向未來借貸，終將連本帶利地還。但這個隱喻的另一面是：如果技術債的利息（理解成本）超過了借貸的本金（開發速度收益），這筆帳就算不過來了。

---

## 五、AI 時代的成本變化

AI 輔助程式設計的出現改變了這個方程式，但不是對稱地改變。

**重寫成本降低了。** 給定明確的規格，AI 能夠快速生成新代碼。今日在一次對話中從概念到可執行的 Rust 平行演算法，在前 AI 時代需要數天的工程時間。這個成本下降是真實且顯著的。

**理解舊代碼的成本沒有對等下降。** AI 對於混亂的遺留系統同樣困惑：沒有文件的變數名、散布在十幾個檔案的業務邏輯、依賴全域狀態的副作用——AI 處理這些的能力並不比有經驗的工程師強多少。上下文視窗的限制讓 AI 更難以掌握大型遺留系統的全貌。

這個不對稱的成本變化意味著：「重寫 vs. 維護」的決策天平在 AI 時代向重寫傾斜了——但傾斜的幅度取決於具體條件，並非一律如此。

---

## 六、病態代碼即有損壓縮

回到編譯的類比：如果原始碼是「人類可讀的意圖表示」，那麼一個充分病態的遺留代碼庫，其實已經完成了一次**對原始意圖的有損壓縮**。

符號語義在技術債的堆積下逐漸損毀：

- 變數名稱失去了與其承載概念的對應（`data2`、`temp_fix`）。
- 函式邊界模糊，一個函式做了十件事。
- 注釋描述的是曾經的行為，不是現在的行為。
- 關鍵的業務邏輯藏在深層的條件嵌套和全域狀態的相互作用中。

到了這個程度，理解這份代碼需要類似反編譯的工作：從行為（binary 等價物）中重建意圖（原始碼等價物）。而如同我們所知，這是一個病態問題——耗時、高風險、且結果充滿不確定性。

當代碼的「信息損失程度」超過某個閾值，Spolsky 的戒律就失去了其前提假設：**如果隱性知識已經無法從代碼中有效萃取，那麼這份「知識庫」事實上已經遺失了**。

---

## 七、決策框架

基於以上分析，提出一個操作性的判斷框架：

**維護優先的條件：**
- 遺留代碼仍然可讀——領域知識仍然可以從代碼本身萃取。
- 代碼包含大量邊界條件處理，且這些條件難以從外部規格重建。
- 系統規模使得完整重寫的風險超出可接受範圍。

**重寫優先的條件：**
- 代碼的信息損失已達到病態程度——理解成本持續高於重新開發成本。
- 存在清晰的外部規格（測試、文件、業務方的描述）可以替代代碼本身作為知識來源。
- AI 工具可以顯著降低重寫的實際成本。
- 技術棧的根本性錯配（錯誤的語言、錯誤的架構、錯誤的計算底空間）使得局部修補無法解決根本問題。

最後一點值得特別強調。正如本文的起點所示——Rust 的平行計算在正確的工作粒度（Mandelbrot）下展現 14 倍加速，在錯誤的工作粒度（迷宮 BFS）下反而慢 10 倍。技術選擇的底層錯誤，無法靠應用層的修補來彌補。如果遺留系統的根本架構與其承載的問題不匹配，那麼任何「維護」的努力，都只是在一個錯誤的計算底空間上堆砌修補。

---

## 八、結語

編譯與反編譯的不對稱性，是信息在單向變換中不可逆損失的一個具體案例。軟體的技術債積累，是對原始設計意圖的另一種有損壓縮。當損失超過臨界點，逆向工程（理解與維護）就成為病態問題。

AI 時代降低了重寫的成本，但不能消除信息損失的基本性質。真正的問題始終是：**那份隱性知識，還在嗎？**

如果在，維護。如果不在了，重寫不是放棄，而是承認損失已經發生，並選擇從現有知識重新出發。

---

## 引用文獻

- Shannon, C. E. (1948). A Mathematical Theory of Communication. *Bell System Technical Journal*, 27(3), 379–423.
- Spolsky, J. (2000). Things You Should Never Do, Part I. *Joel on Software*. https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/
- Cunningham, W. (1992). The WyCash Portfolio Management System. *OOPSLA Experience Report*. (技術債概念首次提出)
- Fowler, M. (1999). *Refactoring: Improving the Design of Existing Code*. Addison-Wesley.
- Brooks, F. P. (1975). *The Mythical Man-Month: Essays on Software Engineering*. Addison-Wesley. (第二系統效應)
- Amdahl, G. M. (1967). Validity of the single processor approach to achieving large scale computing capabilities. *Proceedings of the Spring Joint Computer Conference*, 483–485.

---

*EveMissLab 實驗站筆記 — 非正式發表，僅供研究與理解使用*
