
整理 | 褚杏娟
在上世紀六十年代末,隨著系統規模增長到開發者已無法有效掌控的程度,“軟件危機”(Software Crisis)這一說法首次出現。此后,每一代人似乎都用更強大的工具“解決”了這場危機,但結果往往只是制造出了更大的問題。
Netflix 工程主管 Jake Nations 表示,如今,AI 正在把這一循環加速到一個新的階段:無限軟件危機(Infinite Software Crisis)。由 AI 生成的代碼庫,本質上是生成它們的那一連串曲折對話的映射。每一次澄清、每一次方向調整,都會被直接固化進系統架構中。我們正在用 vibe coding 的方式,一步步走向災難。
Jake?Nations 至今在軟件工程和大規模 AI/ML 系統設計領域擁有 13 年以上經驗,專注于管理復雜代碼庫與推動高質量工程實踐。在 Netflix,他負責推動技術架構與嚴謹開發流程,強調要理解系統本質、控制復雜性以及在 AI 時代保持代碼和設計的可維護性。
針對上述問題,Jake 認為解決之道只有一個:選擇“簡單”,而不是“容易”。一次冗長的對話很容易;而劃分清晰、邊界明確的獨立階段,才是真正的簡單。他提出了一種三階段方法論,并指出,當所有人都在以機器的速度競相生成代碼時,真正能夠脫穎而出的工程師,是那些能夠判斷系統何時開始變得糾纏、復雜的人。在無限代碼生成的時代,人類在最關鍵的節點上進行判斷,將成為核心競爭優勢。
下面是 Jake 的演講分享,我們對此進行了翻譯,并在不改變原意基礎上進行了刪減,以饗讀者。
1 我們正在交付自己并不真正理解的代碼
我交付過一些自己其實并不完全理解的代碼。這些代碼是 AI 生成出來的,測試也跑過,上線也沒出問題,但如果你讓我解釋它到底是怎么工作的,我說不清楚。說實話,我敢打賭,在座的每一個人都做過同樣的事。
所以,不如我們干脆承認一個事實:我們現在都在交付自己并不完全理解的代碼。
我想帶大家回顧一下,這種情況是如何發生的。首先,回顧歷史,你會發現歷史總是在重復。其次,我們其實掉進了一個陷阱:把“容易”和“簡單”混為一談。最后,我認為是有解法的,但前提是,我們不能把“思考”這件事外包出去。
過去幾年,我在 Netflix 推動 AI 工具的落地應用,可以非常負責任地說,這種加速是真實存在的。以前需要好幾天才能完成的待辦事項,現在幾個小時就能搞定;那些在計劃里躺了好幾年的大型重構,終于開始被真正推進。
但問題在于,大型生產系統總是會以意想不到的方式出現故障。看看最近 Cloudflare 發生的事情就知道了。一旦真的出問題,你必須非常清楚自己正在調試的代碼是怎么運作的。而現實是,我們現在生成代碼的速度和規模實在太快了,理解能力已經明顯跟不上了。
說實話,我自己就干過這種事:生成了一大段代碼,看了一眼,心里很清楚自己完全不知道它在干嘛。但測試過了,也能跑,那就先上線再說吧。這其實并不是什么新鮮事。每一代軟件工程師最終都會遇到一個瓶頸:軟件復雜度超出了他們的管理能力。
我們并不是第一批面臨“軟件危機”的人,但我們是第一批面臨這種無限生成規模情況的人。
2 軟件危機,一直在循環
如果我們把時間往前撥,你會看到類似的故事一再發生。
在上世紀六十年代末到七十年代初,一群當時最聰明的計算機科學家聚在一起,提出了一個判斷:我們正身處一場軟件危機之中。社會對軟件的需求急劇增長,但我們的開發能力卻嚴重跟不上,項目周期過長、效率低下,整體表現并不理想。
Edsger Dijkstra 曾有一句非常經典的話,大意是:當我們只有少量、性能很弱的計算機時,編程只是一個小問題;而當我們擁有了性能極其強大的計算機之后,編程反而變成了一個巨大的問題。他解釋道,隨著硬件性能提升了幾個數量級,社會對軟件的需求也成比例增長,最終壓力就全部落在了程序員身上:我們必須在“手段”和“目標”之間找到支撐如此龐大軟件體系的方法。
這種循環不斷上演。七十年代,我們有了 C 語言,可以構建更大的系統;八十年代,個人計算機普及,每個人都能寫軟件;九十年代,對象化編程盛行,繼承層級復雜到失控,某種程度上“感謝”Java;進入新世紀,敏捷開發、沖刺、敏捷教練登場,瀑布模型被宣判“過時”;再后來是云計算、移動開發、DevOps,軟件真正“吞噬了世界”。
![]()
而今天,我們迎來了 AI。Copilot、Cursor、Claude、Codex、Gemini,只要你能描述清楚需求,代碼幾乎可以瞬間生成。模式沒有變,但規模徹底變了:它已經是無限的了。
3 難點從來不在“寫代碼”
Fred Brooks 除《人月神話》作者之外,還寫過一篇非常重要的論文,叫《沒有銀彈》(No Silver Bullet)。他在文中明確指出:不存在任何一種單一的技術創新,能夠在軟件生產率上帶來數量級的提升。
原因很簡單:真正困難的部分,從來不是代碼的機械層面,比如、輸入、樣板代碼這些,而是理解問題本身,并設計出正確的解決方案。這一點,是任何工具都無法替代的。
我們過去發明的所有工具和方法,幾乎都在讓“機械部分”變得更容易,但核心挑戰始終沒有改變:我們仍然需要弄清楚到底該構建什么,以及它應該如何運作。
既然問題不在寫代碼本身,那為什么我們總是在優化這些“機械層面”的東西?為什么經驗豐富的工程師,也會寫出自己看不懂的代碼?
我認為,答案就在兩個我們經常混用的詞上:簡單和容易。
![]()
Rich Hickey,也就是 Clojure 語言的創造者,在他的演講《Simple Made Easy》中,對這兩個概念做過非常清晰的區分。他認為,“簡單”指的是結構上的單一、無糾纏,每個部分只做一件事,彼此之間不互相纏繞;而“容易”指的則是距離上的接近,是不是順手、是不是不用費力就能拿到,比如復制、粘貼、直接上線。
簡單關乎結構,容易關乎便利。
問題在于,簡單是無法靠“許愿”得到的,需要思考、設計和拆解。而容易卻隨處可得:裝個包、讓 AI 生成、從 Stack Overflow 抄一段代碼。人類天生就會選擇容易的那條路。但容易并不等于簡單。容易意味著你可以很快往系統里加東西;簡單意味著你能真正理解自己已經做過的事情。每一次我們選擇容易,其實都是在用當下的速度,換未來的復雜度。
說實話,這種權衡在過去確實是有效的。復雜度積累得足夠慢,我們還有機會通過重構、反思和重建來解決。但 AI 打破了這個平衡。它把“容易”推向了極致,極致到我們甚至不再考慮“簡單”這條路。
4 對話式 AI,正在放大復雜度
當代碼能瞬間生成時,為什么還要思考架構呢?通過對話一步步生成代碼,看起來很自然,也很舒服,但它非常容易把一個本來簡單的任務,演變成一團復雜的混亂。
比如,我們有一個應用,想為它引入一套身份認證機制。我們對 AI 說:“加一個 OAuth 認證流程”,于是生成了一個看起來很干凈的 oauth.js 文件。隨著不斷迭代,又多出來一些配套的處理文件,看起來一切似乎還算合理。接著,我們又提出新的需求:“還要支持另一種 OAuth 認證流程。”于是代碼庫里同時出現了 oauth.js 和 oauth2.js 兩套實現。我們繼續通過對話不斷迭代,很快就發現會話管理開始出問題,各種沖突接踵而至。
到了第二十次迭代時,你已經不再是在“討論設計”,而是在被迫管理一個極其復雜的上下文,甚至已經記不清自己到底引入過多少約束條件。代碼庫里開始出現來自廢棄方案的死代碼,有為了“先跑起來”而被強行修復的測試,還有來自三種不同解決思路的殘留片段,因為每一次新的指令,都會在不知不覺中覆蓋之前的架構決策。
我們說“讓認證邏輯在這里生效”,它照做了;我們說“修復這個錯誤”,它同樣完成了。但它對糟糕的架構決策本身沒有任何約束或抵抗力,代碼只會不斷變形,以滿足你最新提出的需求。
每一次對話,其實都在選擇“容易”而不是“簡單”。而“容易”的必然結果,就是復雜度不斷疊加。AI 會機械地滿足你的每一次最新指令,卻不會對糟糕的架構決策產生任何阻力。
AI 真的把“容易”推向了邏輯極致:你想要什么,代碼就能瞬間得到。但這里的危險在于,生成的代碼會平等對待你代碼庫中的每一個模式。當智能體分析你的代碼庫時,每一行代碼都會變成一個需要保留的模式:第 47 行的身份驗證檢查是一個模式,我 2019 年寫的那段奇怪的、像 GraphQL 一樣工作的 gRPC 代碼也是一個模式。
技術債在 AI 眼里并不是“債”,只是更多的代碼而已。
真正的問題在于復雜度。我知道我在演講中反復提到這個詞,卻沒有真正定義它,但最好的理解方式是:它是簡單的對立面,本質就是“糾纏”。當系統變得復雜時,一切都會相互影響,你幾乎無法只改一個地方而不波及其他部分。每一次交互都是在選擇容易而非簡單,而容易總是意味著更多的復雜度。我們其實知道更好的做法,但當容易的路這么容易走時,我們還是會選擇它。復雜度會不斷累積,直到為時已晚。
回到 Fred Brooks 的理論,他將系統中的復雜度分為兩類:
第一類是本質復雜度(Essential Complexity),也就是問題本身的難度:用戶要支付、訂單要履約,這些決定了系統為什么存在。
第二類是偶然復雜度(Accidental Complexity),這是我們在實現過程中不斷疊加上去的東西:臨時方案、防御性代碼、曾經合理但現在過時的框架和抽象。
在真實的代碼庫里,這兩種復雜度往往糾纏在一起,想要分離它們,需要對歷史、上下文和經驗的深刻理解。而 AI 并不會區分這些,它只會把所有模式一并保留下來。
5 AI 真正需要的不是“更好的提示詞”
有一個來自 Netflix 實際工作的例子。
我們有一個系統,在大約五年前寫的舊授權代碼和新的集中式 OAuth 系統之間建有一個抽象層。我們當時沒有時間重建整個應用,所以就在兩者之間加了一個適配層。現在有了 AI,這似乎是一個直接重構代碼以使用新系統的好機會,對吧?但事實并非如此。
舊代碼與它的授權模式耦合得太緊了:權限檢查穿插在業務邏輯中,角色假設嵌入在數據模型里,OAuth 調用分散在數百個文件中。智能體會開始重構并處理了幾個文件后,就會遇到無法梳理的依賴,然后要么失控放棄,要么更糟。它會試圖保留舊系統中的一些現有邏輯,并使用新系統重新實現,我覺得這也很糟糕。
問題在于,它無法看到表象之下的東西,無法區分業務邏輯在哪里結束、授權邏輯在哪里開始。所有東西都糾纏在一起,即使有完整的信息,AI 也找不到一條清晰的路徑。當你的偶然復雜度到這種程度時,AI 不僅幫不上忙,反而只會在上面添加更多的層。
但我們人類可以區分,至少當我們放慢速度思考時可以。我們知道哪些模式是本質的,哪些只是幾年前某人的解決方案。我們掌握著 AI 可以推斷但需要我們提前花時間區分的上下文。
那么具體該怎么做呢?當你面對一個龐大的代碼庫時,如何區分本質復雜度和偶然復雜度?
我在 Netflix 工作的代碼庫有大約一百萬行 Java 代碼,上次檢查時大約有五百萬個 tokens,我能訪問的任何上下文窗口都裝不下它。因此,在著手處理這個問題時,我最初的設想是,將代碼庫的大量內容直接復制到上下文中,看看模型能否自行識別出關鍵模式并理解系統結構。但結果就和之前的授權重構并無二致,生成的結果很快陷入了自身復雜度之中。
這迫使我不得不嘗試另一種方法:我必須選擇要包含的內容,如設計文檔、架構圖、關鍵接口等等,然后花時間寫下組件應該如何交互以及要遵循的模式。
我其實是在寫一個規格說明。五百萬個 tokens 最終變成了兩千字的規格說明。更進一步,我把這個規格說明轉化為了一套精確的代碼執行步驟,沒有模糊的指令,只有精確的操作序列。我發現這樣生成的代碼更干凈、更聚焦,因為我先定義了需求,再規劃了執行過程。
我把這種方法稱為“上下文壓縮”,你也可以叫它“上下文工程”或“規格驅動開發”,名字并不重要。重要的是,思考和規劃成為了工作的主體。讓我給你們詳細介紹一下這個方法在實踐中是如何運作的。
6 三階段方法論
第一階段:研究。我會把所有相關的東西都提供給 AI,包括架構圖、文檔、Slack 對話記錄。
這一點我其實已經反復強調過很多次了,但核心只有一句話:盡可能把所有與你即將做出的修改相關的上下文一次性帶進來,然后再使用智能代理去分析整個代碼庫,梳理系統的組成部分以及它們之間的依賴關系。
這絕對不是一次性完成的過程。我通常會不斷追問,比如緩存是怎么處理的?失敗場景是如何應對的?如果它的分析有誤,我會直接糾正;如果它缺少關鍵信息,我就補充上下文。每一輪交互,都會讓它的分析更加精細。
這一階段的產出是一份完整的研究文檔:系統里目前都有哪些東西、它們之間是如何相互連接的、你即將做出的改動會影響到哪些部分。原本需要花上好幾個小時甚至更久的探索過程,被壓縮成了幾分鐘的閱讀時間。
我知道 Dex 之前也提到過這一點,但我還是要強調:這里的人工檢查點(human checkpoint)至關重要。這是整個流程中投入產出比最高的時刻,你需要把分析結果與現實系統進行對照,在這里發現錯誤的話就能避免之后發生的災難性后果。
第二階段:制定可以“照著做”的實現計劃。已經有了可靠研究結論的前提下,我們開始制定一份極其詳細的實現計劃,包括真實的代碼結構、函數簽名、類型定義、數據流等。
這份計劃的目標,是做到任何一名開發者都可以直接照著執行。我常把它比作“數字填色”:你可以把它交給團隊里最初級的工程師,對他說“照著這個來做”。只要他逐行照抄,最終結果就應該是正確可用的。
大量關鍵的架構決策,正是在這一階段完成的。我們會在這里確保復雜邏輯是正確的,業務需求遵循良好實踐,服務邊界清晰,職責劃分干凈,同時避免任何不必要的耦合。之所以能在問題發生之前就識別它們,是因為我們曾經親身踩過這些坑。而 AI 并沒有這種經驗,它會把代碼中看到的每一種模式,都當作“必須遵守的約束”。
這一階段真正的“魔法”,在于評審速度。我們可以在幾分鐘之內完成對整個方案的驗證,并且清楚地知道接下來到底會構建出什么。而如果我們想跟上代碼生成的速度,就必須以同樣快的速度理解自己正在做的事情。
第三階段:實現。最后才是實現,一旦我們有了清晰的研究結論和明確的實現計劃,這一步反而應該是最簡單的,而這正是我們希望看到的結果。
當 AI 有一份清楚、具體的規格說明可以遵循時,上下文就會保持干凈且聚焦。我們避免了冗長對話導致的復雜度螺旋。相比五十輪不斷“進化”的代碼修改,現在只需要三次高度聚焦的輸出,而且每一步都會在進入下一階段前完成驗證。沒有被放棄的方案,沒有相互沖突的模式,也不會再出現那種“等等,其實應該這樣”的瞬間,沒有留下遍地的死代碼。
在我看來,這種方法真正的好處是:你可以把大量工作交給后臺運行的智能體來完成。因為所有真正困難、需要動腦子的事情,已經提前由你完成了。智能體只需要按照計劃開始實現。你可以去處理別的事情,回來時只需要快速評審結果,因為你檢查的只是“它是否遵循了計劃”,而不是試圖弄清楚它是不是憑空“發明”了什么。
我們不是用 AI 來替我們思考,而是用它來加速機械性的工作,同時保持我們對代碼的理解能力。研究更快了,規劃更全面了,實施也更干凈了。但思考、綜合和判斷,仍然是我們的責任。
還記得我之前說的那個 AI 無法處理的授權系統重構嗎?現在我們實際上已經開始推進它,并且取得了一些實質性的進展。但這并不是因為我們找到了更好的提示詞,恰恰相反,我們發現,連研究、規劃、實現這些階段都無法一開始就交給 AI。最終,我們不得不親自下場,手工完成這次修改:不借助 AI,只是閱讀代碼、理解依賴關系,然后一步步改動,看哪里會出問題。
說實話,這次人工遷移過程非常痛苦,但至關重要。它揭示了所有隱藏的約束條件、必須遵守的不變式,以及一旦授權邏輯發生變化,哪些服務會直接崩潰。這些信息,是任何自動化代碼分析都不可能替我們挖掘出來的。
然后,我們把這個手動遷移的拉取請求納入了研究過程,讓它作為后續所有研究工作的基礎。即便如此,由于不同實體之間仍然存在差異,我們還是需要不斷追問:這個該怎么處理、哪些數據是加密的哪些不是,每一次都要補充額外的上下文,并經過多輪迭代。
直到這時,我們才有可能生成一份“或許能一次成功”的計劃。注意,這里的關鍵詞是“或許”。我們仍然在持續驗證、不斷調整,并持續發現新的邊界情況。
這套三階段方法并不是什么魔法。它之所以能奏效,只是因為我們曾經親手完成過一次遷移。在把理解寫進流程之前,我們必須先贏得這種理解。
我依然認為,并不存在所謂的銀彈。沒有更好的提示詞,沒有萬能的模型,甚至也不是寫得更漂亮的規格文檔。真正重要的,始終是那件最樸素、也最困難的事情:足夠深入地理解你的系統,理解到你可以安全地對它做出修改為止。
那為什么還要折騰這一整套流程呢?為什么不干脆一直和 AI 反復迭代,直到“能用”為止?反正模型遲早會變得足夠強,最后不就都能跑起來了嗎?
在我看來,“能跑”本身并不夠。通過測試的代碼和能在生產環境長期穩定運行的代碼之間,是有本質區別的;今天還能工作的系統,和未來還能被別人安全修改的系統,也是兩回事。
這中間存在一個認知鴻溝。當 AI 可以在幾秒鐘內生成成千上萬行代碼時,理解這些代碼卻可能要花你幾個小時;如果系統足夠復雜,可能需要幾天;甚至在極端情況下,你可能永遠都無法真正理解它。
7 軟件,終究是一項人類的事業
還有一個我覺得幾乎沒人認真討論過的問題:每一次為了跟上生成速度而跳過思考,我們失去的并不只是對代碼的理解。我們正在逐漸喪失一種能力:識別問題的能力,那種會提醒你“等等,這里開始變復雜了”的直覺,如果你長期不真正理解自己的系統,是會慢慢退化的。
模式識別(pattern recognition)來源于經驗。我一眼就能看出某種架構是危險的,那是因為我就那個曾經凌晨三點還在被它折磨的人;當我堅持推動更簡單的方案時,是因為我曾經接手并維護過別人留下的復雜系統。
AI 只會生成你讓它生成的東西,它并不會內化那些來自失敗的教訓。
三階段方法,正是用來彌合這道鴻溝的。它把“理解”壓縮成一系列可以在生成速度下被快速審查的產出物。如果沒有這一層,我們只是在用一種自己無法理解的速度,不斷累積復雜度。
AI 確實徹底改變了我們寫代碼的方式,但坦率地說,我并不認為但它并沒有改變軟件失敗的根本原因。每一代人都會遭遇屬于自己的軟件危機。Dijkstra 那一代,通過建立軟件工程這門學科來應對;而我們這一代,面對的是無限規模的代碼生成。
答案并在于下一個工具或新的方法論,而在于重新記起一個我們早就知道的事實:軟件始終是一項人類的事業。困難的從來不是敲代碼,而是在一開始就知道該敲什么。
最終能夠走得更遠的開發者,并不只是那些生成代碼最多的人,而是那些仍然理解自己在構建什么、能夠看清系統接縫、敢于質疑問題本身是否正確的人。
我想用一個問題來結束今天的分享,這個問題并不是“我們會不會使用 AI”,那早已是既定事實。真正的問題是:當 AI 寫下大部分代碼的時候,我們是否仍然理解自己的系統?
https://www.youtube.com/watch?v=eIoohUmYpGI
技術人的年度儀式感! 年度盤點與趨勢洞察 啟動!
《2025 年度盤點與趨勢洞察》由 InfoQ 技術編輯組策劃。覆蓋大模型、Agent、具身智能、AI Native 開發范式、AI 工具鏈與開發、AI+ 傳統行業等方向,通過長期跟蹤、與業內專家深度訪談等方式,對重點領域進行關鍵技術進展、核心事件和產業趨勢的洞察盤點。
力求以體系化視角幫助讀者理解年度技術演化的底層邏輯、創新方向與落地價值,并為新一年決策提供參考。內容將在 InfoQ 媒體矩陣陸續放出,歡迎大家持續關注。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.