Part 5 開始。往回走一步。
而這一步接的是 Part 4 的主軸。 前面七天處理的是「以為驗證過了,其實沒有」;接下來四天要處理它的上游版本。
以為理解過了。
前面所有的檢查、規格、閘門,都建立在同一個前提上:你知道要做什麼。 而當你接手的是一套沒有人看得懂的舊系統,那個前提就不成立了。前面三十五天處理的都是「產出」。寫程式、建工廠、驗證。而它們有一個共同的前提:你知道要做什麼。
但很多專案的起點不是這樣。起點是一套跑了十幾年、沒人完整看得懂的系統,而你要接手它。
這四天講那件事。
我知道在第三十六天丟一篇四十年前的學術文章有點怪,但它是這一段的地基。論文叫《Programming as Theory Building》,作者是 Peter Naur。它的主張可以濃縮成一句:
程式設計的產物,不是程式碼,而是程式設計者腦中的「理論」。
這裡的「理論」不是學術意義的理論,比較接近一套完整的心智模型:這個系統為什麼長這樣、每個決策當初在解決什麼問題、哪些是刻意的、哪些是妥協的、要改某個東西該從哪裡下手。
而 Naur 用的那個定義更嚴格,而且不是他自己的。他借的是哲學家 Gilbert Ryle 在《The Concept of Mind》(1949) 裡的說法:
理論是「一個人為了不只能夠聰明地做某些事,還能夠解釋它們、回答關於它們的問題、為它們辯護,所必須擁有的知識」。
注意「能夠辯護」那幾個字。 這是我覺得最狠的一個判準:你能不能為一個設計辯護,決定了你到底有沒有真的懂它。(這個歸屬我一開始寫錯了,寫成「Naur 自己給的定義」。是後來回頭核對才發現的。而這正好是後面要講的那種錯:觀察對、詮釋錯。)
而程式碼和文件,都只是這個理論的投影。
Naur 由此推出三件事:
第三點就是 legacy 的定義。
Naur 用「腐化」(decay)解釋程式為什麼會越改越爛,而他給的病因非常精確:
腐化來自「在未恰當掌握底層理論的情況下所做的修改」。
拆開來看是這樣:同一個修改需求,通常有很多種寫法都「正確」。都會編譯過、都會通過測試、行為都符合需求。
但放在理論之下看,這些寫法非常不同。 有些是順著既有結構自然延伸的,有些是在主體上打了一塊補丁。
而兩者的差別只有持有理論的人看得出來。
Naur 舉的那個編譯器案例,結局是這樣的:一支結構優雅的編譯器,被沒有原團隊指導的後人持續修改,十年後原作者回頭看,發現「原本強而有力的結構仍隱約可見,卻被各式各樣雜亂無章的添加物弄得完全失效」。
現在把 AI 放進這句話裡:
AI 對「怎麼改最合適」的判斷,
依據的是它從文字表面歸納出來的統計相似性——
而不是 Naur 說的那種「只對理解世界的人才有意義」的相似性。
所以在沒有理論持有者把關的情況下讓 AI 自由修改,等於是給腐化裝了渦輪。這也解釋了前面三十五天講的所有東西為什麼有必要。那些檢查、規格、閘門,本質上都是在替代那個「掌握理論的人」,去判斷這次修改是延伸還是補丁。
而它們只能替代一部分。這是後面要老實面對的事。
我以前一直以為 legacy 是技術問題。框架太舊、資料庫太老、沒有測試。做過幾個遷移案之後,我的看法變了:
你的系統不是因為用了十五年前的框架才叫 legacy。
它叫 legacy,是因為當初知道「為什麼要這樣做」的那些人,都離職了。
我遇過技術棧非常舊、但團隊還在、文件也還算完整的系統。那種要遷移其實不難,因為你隨時可以問到「為什麼」。也遇過技術棧不算太舊、但寫的人全走光的系統。那種才真的痛,因為每一行看起來多餘的程式碼,你都不敢刪。
Naur 這篇寫於 1985 年,這兩年被大量重新提起,我認為原因很直接:
以前產出文件很貴,現在幾乎免費。
過去要產出一份三百頁的規格書,得投入好幾個人月。這個成本本身就是一道天然的過濾器。你不會為了一個你不理解的系統去寫三百頁文件,因為太貴了。
所以「文件很少」是一個看得見的問題,沒有人會誤以為自己懂了。現在不一樣。現在你可以在完全沒有建立任何理論的狀態下,擁有一整櫃看起來很專業的文件。
文件的豐富度和理解的程度,第一次徹底脫鉤。
而且這個脫鉤是不對稱的:文件豐富度看得見(可以量、可以交付、可以報進度),理解程度看不見。所以在專案管理的視角上,前者會被獎勵,後者會被忽略。
這正是 Day 05 那個場景。需求文件十天全部產完,報告寫著「100% 完成」,而所謂完成的定義只是「產出了檔案」。沒有人答得出「這些規格是對的嗎」。

這一段一定要寫,因為不寫就是選擇性引用。Naur 對「復原理論」的立場比我強硬得多:
僅憑文件重建一支程式的理論,嚴格來說是不可能的(strictly impossible)。
注意措辭。不是「困難」、不是「不划算」,是「嚴格不可能」。
而且他給的建議更狠。與其復活,不如把既有程式碼丟掉,讓新團隊重新面對問題。理由是:「為了契合並支撐一份既有程式碼而去建立理論,是困難、令人挫折且耗時的」,而重新解題「更可能產出一支可存續的程式,成本不會更高、甚至可能更低」。
如果照這句話走,這一整段就不必寫了。答案是「別逆向,重寫」。
所以我要說清楚差別在哪。
一、我做的不是「僅憑文件」。
Naur 那句話的限定詞是 merely from the documentation。而後面幾天講的做法。執行切片、七觀點、來源行號綁定。輸入不只是文件,還包括跑得起來的舊系統,以及還在的業務方。
這三者的可信度完全不同,分清楚它們是整套做法的地基:
| 來源 | 是什麼 | 能回答 |
|---|---|---|
| 規格與文件 | 待驗證的假設 | 「當初宣稱要做什麼」 |
| 跑得起來的系統 | 事實 | 「它實際上做了什麼」 |
| 還握有理論的人 | 真相 | 「為什麼要這樣做」 |
文件會過時、會從沒實作過、會是一廂情願。而跑起來的系統不會騙人。但它也不會告訴你為什麼。
所以做法是:拿到規格不要直接照做,往下一層去驗;驗到了「做什麼」還缺「為什麼」,就得去找人。這就是 Naur 說的 work in close contact,只是換成了工程實作的形式。
二、我沒有宣稱能復原完整的理論。
能復原的是行為的完整覆蓋加上一份誠實的未知清單。而「為什麼」那一塊,如果沒有人能回答,正確的處理是登記成「無法考證」,不是讓 AI 填一個看起來合理的理由。
三、而「丟掉重寫」在現實中常常不是選項。跑著真實的錢、有法遵要求、有一百個在用的使用者,你不能跟客戶說「Naur 說應該丟掉重來」。
但他那句話仍然有用,用法是當成本校準:
如果逆向做到一半,發現「為什麼」幾乎每一條都答不出來——
那不是要更努力逆向,是該回頭認真評估重寫。
Naur 給的不是禁令,是一個該被放上天平的選項。而多數專案從來沒有把它放上去過。
四、還有一件事他大概也不會喜歡:我一直在用「工廠」這個詞。
因為 Naur 在同一篇裡明白批判過「生產觀點」。把工程師當成「產出活動裡容易被替換的元件」,把設計當成能沿著輸送帶組裝、打包外送的貨物。
我的辯解是 Day 19 那個二分:**我工業化的是工站,不是閘門。**規格產出、跑檢查、比對、量測。那些可以放上輸送帶。而「這個欄位該不該必填」「這道檢查該抓什麼」「這條規則為什麼存在」。那些從第一天就不在輸送帶上。
如果哪一天連閘門也自動化了,那就真的是 Naur 批判的那個東西了。 而且它的下場會很具體:新系統上線第一天,行為全對,但沒有任何人持有它的理論。出生即死亡。
理論講完了,明天處理它的實務面:既然逆向出來的東西只是假設,那要怎麼做、分工怎麼切、產出該長什麼樣、什麼情況下不能只靠它。