關於程式碼閱讀
談一下我自己對於「到底要不要看程式碼」的看法吧。
其實對我來講,我是主張「不要一行一行去讀程式碼」的立場的,這點在基於過程的質量控制裡面就談到過。不過這裡面可能需要做一個分層,就像之前所說的一樣,你需要對自己的程式碼進行分層。比如說特別重要的、可能會危害人生命的,那這種程式碼最好還是一行一行去讀,對吧?第二層就是,可能涉及到大規模的金融處理,或者很重要的核心核心,那可能還是要看一下。但越往後,可以說我們日常構建的90%以上的程式碼都不涉及這兩個方面。這種情況下,我認為尤其是在當今的時代,一行一行去讀程式碼已經沒什麼意義了。
因為它會成為一個嚴重的效率瓶頸。像我自己一直強調說,我現在一整天就能產生一萬行程式碼,如果我要去把它全部讀一遍,那我個人就會成為瓶頸,對不對?而且在沒有上下文的情況下,我去讀程式碼更痛苦的是我。根據一些測試報告顯示,人類去讀程式碼一個小時最多也就幾百行,你要把一萬行看完,今天一整天就只能在那看程式碼,而且還頂不住。
所以我認為,不讀程式碼是完全可以接受的。只是「不讀程式碼」並不等於我放棄了對程式碼的質量控制。尤其是 AI 寫的程式碼,很多時候會越寫越偏,甚至越寫越出問題。所以我還是會去讀,但不是一行一行讀。什麼叫「還是會去讀」呢?我的讀,是讓 AI 幫我總結,然後看大概的架構、看摘要,進行抽象性的閱讀。現在可能我真的都不怎麼看程式碼原文了,程式碼原文對我來講更像是一種中間產品。我會更多地專注於整個質量控制體系的建構,就像 Harness 約束 AI 一樣。
比如說,構建一個非常完善的測試覆蓋。而且這種測試覆蓋不能單純由一個 Agent 來構建,因為它們會出現一個經典的老問題,就是「暗度陳倉」。什麼意思呢?就是編一些「假綠」——哪怕你程式碼真的出問題了,它也可能最終給你顯示測試通過。你說這種測試有什麼意義?這就是先射箭後畫靶。所以這種測試要靠什麼?一是靠對抗性的審查來構建,比如專門出一個沒有任何上下文的 Agent 去審它;或者讓它去進行變異測試,也就是把原文故意改壞,看它測試結果還綠不綠,如果改壞了還綠,那就是假綠。為了實現這一點,最好是把寫變異測試的這個過程給指令碼化、自動化,而不是讓 AI 去寫變異測試,防止沒跑過就出問題。
第二點就是增加各種各樣的測試手段,像迴歸測試、整合測試、E2E 測試等。其中有一個很關鍵的點是「對齊需求」。什麼叫對齊需求?就是有時候就算測試通過了,它通過的內容跟我想要的也不一樣。它在程式邏輯上是合理的,也確實沒 Bug,但它測的是一個錯誤的行為。我的規格想要的是 A 行為,它完完全全寫了一個跟 A 完全不一樣的 B 行為,然後讓測試通過了。這就叫沒有對齊我的需求和規格。
就像有些人說的,逐行閱讀其實不現實,而且「假裝逐行閱讀」反而更糟。每次看個四五百行,你的閱讀質量就會一直下降。你真的連續 Review 一天程式碼,看到後面會不知所云的。人在這個時候,正確率還不一定有機器高。大量的程式碼把你淹沒了,最後你根本就不想去看,效率會變得非常低。與其搞這種沒什麼意義的 Review,不如去構建一個完整的、全面的、工程化的測試環境。
你可以看看 StrongDM 他們那種有點像是「黑燈工廠」、「軟體工廠」的開發形式。他們的態度非常強硬,要求程式碼絕對不能由人編寫,也不得由人進行審查。那他怎麼去保證程式碼質量呢?就是靠我所說的,構建一個足夠過硬的工程環境。這一點其實有點像什麼呢?就是一個是從內部保證,一個是從外部約束。要麼是從內部保證你的程式碼本身質量夠高,寫得一點 Bug 都沒有;要麼就是,就算有 Bug,I don’t care,我哪怕把你當成一個黑匣子都行,但我需要用各種各樣的外部套件、各種各樣的測試,保證你的整個行為被壓制在我希望的範圍之內。這就叫外部約束。
我認為這種外部約束意味著邊界和塑形。一個是拿外部的框架當模子把它套進去,另一個是從一開始就捏出這個模子。這沒有說誰真的一定是對是錯,兩邊都有自己的道理。但是從效率的角度來考量,堅持去人工 Review,在我看來遲早會落後於時代,因為它的效率瓶頸實在太高了。
StrongDM 有一個很有意思的測試我還挺喜歡的,就是他們會構建一個完完全全的數字克隆環境(DTU,Digital Twin Universe 數字孿生宇宙)。他們把軟體所依賴的第三方服務進行了一個行為克隆,用來檢測當軟體接入外部時會出現什麼錯誤。說白了就是模擬一個真實的運轉環境,去不斷地對它進行測試。而且他們的測試強度很高,比如進行高容量的壓力測試、故意進行攻擊、製造危險的故障等。重點是,他們的測試條件都是可驗證的,而且測試頻率很高。
他們還有個機制叫做 Gene Transfusion(基因注入/基因移植)。不過他們這個看進去更像是把一些標準的範式提取出來,在不同的程式碼之間遷移相似的工作模式。它不只是用 Skill 來保證,更像是有某種特殊的依賴,或者一個固定的結構和機制。這跟我的用法是類似的,我把它理解為構建了一套可複用的、現代化的開發方法論,它在每一個地方的行為都是可複用、可遷移的,而不只是繫結在一個庫上。
在檔案管理方面,他們也有完整的規範。系統會完整地記錄各種各樣的中間記憶檔,尤其是對核心檔案進行管理。目錄的名字是有意義的,會建立各種索引,然後把中間的狀態完完整整地寫回到磁盤裡去。就是要使整個倉庫內部的 Agent 時刻有記憶,而不是每次都重新開始。這一步是為了讓 Agent 能夠持久化整個環境,讓它下一次開發的時候能直接撿起來繼續做。這個做法其實大家最終都會往這個方向湧現。
此外,他們有兩種執行模式:一種是互動式的,有 Human-in-the-loop(人類參與);還有一種是完全非互動式的,只要給出規範,它就從頭跑到尾。非互動式的這個挺有意思,它寫完之後,還會構建一個像吸引子一樣的節點圖迴圈。比如先實現功能,然後找到瓶頸,再去最佳化效能。在這個過程中,它通過一整套可驗證的行為和結果,保證在這個迴圈中能得到明確的反饋。同時,他們還會用一個獨立的 LLM 去進行評估,過程是可觀察的,結果是確定性的。就像現在流行的一種圖程式設計,通過有向無環圖(DAG),從請求、計劃到呼叫方案、嘗試、成功、返回。
我可以這樣理解:他們試圖在構建一個能夠自動化執行且自動化糾正的系統。而這種系統的關鍵點有兩個:第一它是能從頭跑到尾的;第二它是能遇到明確反饋並且能夠自我糾正的。在這裡,「可驗證性」就極其重要了。如果你的可驗證性上不來,那 Agent 就會一跑就跑沒邊,陷入死迴圈,從而出問題。另外,中間還會加上跨 Agent 的獨立審查,用層層流程來保證質量。
這也印證了一個我很贊同的觀點:我們現在的開發關鍵點,已經從「程式碼本身」轉移到了「行為」以及「驗收標準」上。也就是,什麼樣的程式碼運作狀態是可驗收的?什麼樣的行為是我預期想要的?我們其實是在設計一個個非常嚴格的關卡,希望 AI 能通過這些關卡,沒通過就要把它補上。在這個過程中,Agent 的思維跳脫就被一定程度地限制住了。
其核心理念就是 Agent 需要紀律。我們需要去保證它工作的有效性,而這種有效性就是通過嚴格的過程和質量閥門(門控)來保證的。我可以不去審每一行程式碼,但是我一定要有可驗證的指標和關卡,來確保程式碼確確實實是有質量的。
當然,對我來講有些東西我是不可能不讀的。比如涉及到具體功能該怎麼設計,或者是整體的架構。我至少得對整個架構有理解和把握,我不可能自己設計的系統,卻不知道它長什麼樣。我可以不關注程式碼層面的細節,但是宏觀上的細節和架構我是一定要了解的。
所以我想,未來整個開發的趨勢,應該就是不斷去加強這樣一套工程關卡的建設吧。
The right not to read the code | Raphael Moura StrongDM Software Factory https://arxiv.org/html/2606.13175v1