軟體不是由程式碼構成的

發表於

軟體不是由程式碼構成的,而是由決策構成的——要做什麼、要驗證什麼,以及有多少工作可以交給機器。程式碼只是這些決策最後落腳的地方。

五十年來,我們相信的是另一回事。「軟體工廠」這個概念可以追溯到 1968 年 Bob Bemer 的論文〈The Economics of Program Production〉,半個世紀以來,這個夢想都建立在同一個假設之上:開發可以從個人孤立的技藝,轉化為可重複、可量測的生產流程。這個夢想大多落空了——「沖壓出想法」終究不同於沖壓汽車零件。

但在過去兩年間,情況已經劇烈改變。LLM 驅動的 coding agent 讓這個舊夢獲得了新的技術基礎——生成變得便宜、快速,而且幾乎沒有上限。也正因為興奮之中很容易迷失,我們有必要把話說清楚:有些看起來新的東西確實是新的,有些則是披著新機會外衣、反覆出現的陷阱。這個差別值得精確地說明。

如果說 diff 是工作的抽象、測試套件是正確性的投影,那麼驗證就是軟體的底層現實。 這篇文章接下來的一切,都從這句話推導而出。

三層堆疊:迴圈、Harness 與工廠

整個架構可以理解為三個層層相疊的概念:迴圈、harness,以及工廠。

第一種單位是迴圈。迴圈是 agentic work 的最小單位:一個 agent 重複執行「收集脈絡 → 採取行動 → 檢查結果 → 重新來過」,直到某個條件滿足為止。它的品質標準是:能不能有用地終止,以及那個結果能不能便宜地被檢查。迴圈工程的核心轉變在於:你不再一個回合一個回合地手動 prompt agent,而是設計一個小系統,由它來替你 prompt agent。

第二種單位是 harness。Harness 是圍繞迴圈的邊界:它運行的沙盒、它能觸及的工具、在兩次運行之間存續的記憶,以及決定「完成」意味著什麼的閘門。迴圈是行為;harness 是行為運行的環境。一個未經 harness 包覆的原始模型,會無止境地空轉下去。Harness 是它周圍一切讓它得以有用且安全運行的事物。

第三種單位是工廠。軟體工廠是許多被 harness 包覆的迴圈同時運行,由一個工作佇列(queue)餵入,經由審查閘門(review gate)排入生產環境,人類在頂層掌管整體方向。它不是一個更大的 agent;它是一張由迴圈組成的組織圖。

最終的典範轉移,是從撰寫程式碼,轉變為建置並運行那座會撰寫程式碼的工廠。 工作的單位向上提升一層——變成迴圈、harness,以及它們之間的流動——而不是單一的程式碼 diff。

閉合迴圈與那個頑固的節點

一個 agentic 軟體工廠構成一個閉合迴圈:意圖與生產環境訊號流入待辦事項佇列,harness 從佇列中挑選項目並建置變更,自動化檢查為變更把關,部署將它送出,監控再把生產環境的狀況轉回為驅動佇列的訊號。

在這個架構中,幾乎每一個方塊的成本都極低。生成、測試、掃描——它們都能以微不足道的代價大規模運行。只有一個方塊被證明頑固地抗拒擴展:審查閘門。那個代表「判斷力」的節點,正是整個論戰的核心所在。

暗燈工廠與理解債

「暗燈工廠」一詞借用自製造業。實體工廠在燈光關閉的狀態下運行,因為廠房裡只有機器,而機器不需要光。在軟體中,暗燈工廠意味著:交付的程式碼沒有任何人在任何階段閱讀過,只由其他機器驗證。

這是一件驚人地容易達成的事,至少在一開始是。它容易,是因為被省略的審查步驟擋住了其他一切。它的缺席,會讓團隊垂直吞吐量的感知突然且劇烈地升高。但要在暗燈工作流程中長期存活,比表面上看起來困難得多,因為它們埋藏著一項隱性成本:理解債(comprehension debt)。

理解債指的是程式碼存在的數量與任何人類仍然理解的數量之間,不斷擴大的差距。暗燈工廠不會償還這筆債;它會以最快的速度把這筆債攬上身,而且整個過程中測試都是綠燈。模型在某些任務上表現得很好,但對於任何不是對程式碼庫小部分立即變更的工作——尤其是在複雜的既有系統中——純模型的自動化編碼會面臨無法逾越的障礙。一個開發十年以上的企業級系統,必須在專業的環境中、以專業的節奏被維護。當專案進行到三至六個月時,團隊已經淹沒在未曾被人類閱讀過的程式碼裡。

暗燈工廠真正擅長的,是在測試保持綠燈的同時,快速消耗乾淨的程式碼。最終的清算不會是戲劇性的全面失控——它會是安靜的,而且來得很晚。

為什麼驗證才是關鍵

軟體工廠的根本限制,不是我們能產出多少程式碼,而是我們能多快地驗證它。

背壓(back pressure)是一條根本規則:你只能授予一個迴圈與你能夠便宜且可靠地驗證的部分一樣多的自主權,一寸也不能多。 驗證,而不是生成,才是工廠真正的限制。無上限的生成能力與人類注意力這個有限且無法擴展的資源之間,存在著永恆的張力。數量本身不是問題:真正造成損害的是不良 PR 的過剩。當你有高產量卻沒有可信賴的閘門時,缺陷的產生就無可避免。

每一場生產革命都在回應一種稀缺。生產線回應的是稀缺的勞動力;軟體工廠回應的則是人類注意力——一種忽略它從來沒有像現在這麼廉價的稀缺。這裡還有第二階的問題:為什麼改進模型本身,不應該自動縮小它能生成之物與能被驗證之物之間的差距?因為衡量架構卓越的成本函數不是以秒或分鐘來計量的,而是以月與年。平滑的梯度在功能上無法計算,所以一個期望對複雜設計決策進行清晰、即時評估的系統,是無法用良好範例來訓練的。架構品質的訊號本質上就是稀疏且延遲的。模型會越來越好,但這個落差不會自己縮小。

亮燈工廠:把判斷移到上游

亮燈工廠是同一條管線,只是判斷力留在該在的地方。Agent 仍然完成大部分建置工作,但人類在交付前會閱讀產出,而且在任何一個錯誤判斷代價高昂的地方,人類的注意力持續在場。

亮燈版本的關鍵差異,不是把審查掛在末端,而是把人類判斷的節點移到上游——移到產品、設計與架構階段——在 agent 開始一個迴圈之前。那個前置的投入會帶來更少的實作時數:它把一次漫長、令人沮喪的程式碼審查,變成快速閱讀一份兩百行的計畫。決策在成本複利化之前就被人類審視過了。

這張安全網,是由我們一直以來都知道、卻大多忽略的、完全普通的架構實踐所組成:良好的型別與方法簽名(method signature),讓錯誤在編譯器就被捕捉;測試縫隙(test seam),讓我們能釘住行為、讓變更可被觀察;清晰的程式碼佈局,讓下一位讀者——無論是人類還是模型——知道該去哪裡找他們關心的東西;簡短易讀的呼叫堆疊;定義清楚的元件邊界,使單一變更不會有巨大的爆炸半徑(blast radius);以及依賴注入(dependency injection),讓我們能把一個元件換成另一個。

這些沒有一樣是新的。我們一直說我們在乎良好的架構,但現在我們在使用自動化 coding agent,這套架構終於有了第二份工作:充當一道便宜、難以偽造的安全網,對抗 agent 會犯的錯誤。那張安全網必須存在於模型之外,因為模型不會自己提供它。效能最強的 coding agent 是針對自己的 harness 與工具進行強化訓練的——它們對行業內的工具與慣用語駕輕就熟,但對長期可維護性這類關切卻並非如此。深思熟慮的架構,正是捕捉那筆債的工具,而我們對它的投資,就是我們買回自主權的方式。

什麼能讓一個迴圈贏得自動化資格

一個迴圈要贏得完全自動化的資格,只有當它的檢查便宜、高頻率運行,而且依賴某種不容易被偽造的東西時才成立。綠/紅神諭(green-or-red oracle)、型別閘門、性質測試(property test),以及搭配真正評分標準(rubric)的審查 agent,都符合條件。你還需要神諭立即給出答案,而且不會隨時間漂移。當「完成」不僅能被你證明,也能被機器證明時,就達到了自動化。

短迴圈比長迴圈更容易驗證。一個經驗法則是:agent 能穩定維持三到十步,超過二十步就開始失去頭緒。原因是脈絡累積(context accumulation)——agent 拖著越多東西走,就越可能偏離主題。當迴圈短時,驗證它是便宜的;蔓生的迴圈把錯誤藏在角落裡,換句話說,它們從來沒有贏得自動化的資格。

保持人類參與則是相反的情況。當錯誤答案的代價高昂,而且只有人才能捕捉到它時,這個迴圈就需要被審查:測試抓不到的細微生產 bug、巨大的爆炸半徑,以及會塑造未來一年或更久工作的決策,都符合資格。在那些情況下,人類注意力才是真正的產品——昂貴、不可或缺。

真正的危險不在於選擇全暗或全亮,而在於忘記逐一評估每個迴圈。全部暗燈,數月後就得拆掉一切。全部亮燈,審查瓶頸會吞沒整個流程。那件困難、需要技藝的工作,是決定每個開關該放在哪裡。

被畫成圖的背壓

當你交給 agent 一個任務時,你很可能會圍繞它建構一張圖——無論你稱之為有限狀態機,還是一組條件式連結的服務呼叫。這是一種框架,其中軟體不只是遵循抽象規則,而是一個結構化的工作流程:每個節點是一個明確的步驟,每條邊是一條明確的條件。

這裡真正值得注意的洞見是:軟體本來就一直有那個結構。任何程式碼都可以表達成一張控制流程圖(control-flow graph)。真正新的舉動,是試圖把那張圖扔掉,依靠一個純粹的迴圈,讓模型一個 tool call 接一個 tool call 地自己選路徑,直到它宣稱完成。那感覺像解放,直到它遇到一個十年的程式碼庫。每個人現在正在重新發現的紀律——掌控自己的控制流程——其實只是繞著迴圈把那張圖走回來。

那張圖真正的價值在於它是一張被畫成圖的背壓。你放棄 agent 的一些自由,換來強制的檢查與清晰可讀的失敗點——當一個 run 失敗時,你可以精確地指出殺死它的節點。這也呼應了一個關鍵觀察:大多數所謂的 agent 其實一點都不 agentic,它們大多是可確定性的程式碼,只是在恰到好處的點上引入了 LLM 步驟。這個模式在 LangGraph、LlamaIndex Workflows 以及各種混合式 workflow-graph-over-agents 的架構中反覆出現。本質上,這只是狀態機和 actor model 在當代技術條件下的重新登場。

人的角色:外層迴圈

人類從來沒有離開工廠——他們移動了位置。

Agent 可以調查一個 bug、寫出診斷、實作修復、跑測試、寫出報告。那是內層迴圈(inner loop)的執行,agent 可以做得跟任何人一樣有效率。但那從來不是工作的全部。人類擁有的部分,是外層迴圈(outer loop):決定這是不是處理問題的正確方式、驗證診斷與實作是否健全、核准變更,並承擔判斷錯誤的後果。

兩個迴圈之間的邊界是證據——diff、測試、日誌,以及一段把這些串連起來的簡短說明。型別、縫隙和評分標準,讓你在不必為每項變更做大量工作的情況下,維持有效的監督。

你可以做很多事讓模型更好、讓 harness 更能幹,但找出長期代價高昂的問題,通常不是能自動化的事情。仍然是人類工作核心的,是比任何運算能力的流動都更好地行使人類判斷力。

邊界正在移動,以及接下來會是什麼

軟體工廠的核心命題不是取代人類,而是重新界定人類判斷力應該部署在何處。暗燈與亮燈不是二擇一的選項,而是一個需要針對每個迴圈逐一評估的決策矩陣。自動化與審查之間的界線不是固定的——驗證變得便宜、高頻、難以偽造的地方,界線就往前移;而在一個錯誤判斷代價高昂的地方,界線就守在那裡。

接下來會出現的不是單一的模式,也不是單一的模型。而是一座工廠:自主權被授予到驗證能力所及之處為止——一個迴圈接著一個迴圈、一個 harness 接著一個 harness——而其中最有價值的工程工作,已經完全不是寫程式碼了,而是持續判斷每一個迴圈應該獲得多大的自主權。

軟體不是由程式碼構成的,而是由決策構成的;而工廠真正的產物,是知道每一個決策該在哪裡做成。 燈不是開或關,而是一張決策矩陣——每一個開關,都得有人去撥。

回到研究與洞察