Rob Pike的“抱怨”與Go的“解藥”:直面軟件膨脹的四大根源
今年年初,Go語言之父、UTF-8編碼的發明者Rob Pike的一篇題為"On Bloat"(關于膨脹)的演講幻燈片(在2024年下旬做的)在技術圈,尤其是在Hacker News(以下簡稱HN)上,引發了相當熱烈的討論。Pike作為業界泰斗,其對當前軟件開發中普遍存在的“膨脹”現象的犀利批評,以及對依賴管理、軟件分層等問題的深刻擔憂,無疑戳中了許多開發者的痛點。
HN上的討論更是五花八門,開發者們紛紛從自身經歷出發,探討“膨脹”的定義、成因和后果。有人認為膨脹是“層層疊加的間接性”導致簡單修改寸步難行;有人認為是“不必要的功能堆砌”;還有人歸咎于“失控的依賴樹”和“缺乏紀律的開發文化”。
那么,Rob Pike究竟在“抱怨”什么?他指出的軟件膨脹根源有哪些?而作為我們Gopher,Go語言的設計哲學和工具鏈,能否為我們從純技術層面提供對抗膨脹的“解藥”呢?今天,我們就結合Pike的演講精髓和HN的熱議,深入聊聊軟件膨脹的四大根源,并從Go的視角嘗試尋找一下應對之道。
“膨脹”的真相:遠不止代碼大小和運行速度
在深入探討根源之前,我們需要認識到,“膨脹”并不止是字面意義上我們理解的最終編譯產物的大小或者應用的運行速度慢,Pike的觀點和HN討論中的“軟件膨脹”體現在多個維度:
- 復雜性失控: 過度的抽象層次、復雜的依賴關系、難以理解的代碼路徑,使得維護和迭代變得異常困難。
- 維護成本劇增: 添加新功能的長期維護成本(包括理解、測試、修復Bug、處理兼容性)遠超初次實現的成本,但往往被低估。
- 不可預測性與脆弱性: 龐大且快速變化的依賴樹使得我們幾乎無法完全理解和掌控軟件的實際構成和行為,任何更新都可能引入未知風險。
下面我們具體看看Pike指出的“膨脹”幾個核心根源:
根源一:特性 (Features) —— “有用”不等于“值得”
圖片
Pike 指出,我們不斷地為產品添加特性,以使其“更好”。但所有特性都會增加復雜性和成本,而維護成本是最大的那部分,遠超初次實現。他警示我們要注意“有用謬論” —— 并非所有“有用”的功能都值得我們付出長期的維護代價。
HN討論也印證了這一點:功能冗余、為了匹配競品或滿足某個高層“拍腦袋”的想法而添加功能、甚至開發者為了個人晉升而開發復雜功能的現象屢見不鮮。
技術層面:Go的“解藥”在哪?
- 簡潔哲學: Go從設計之初就強調“少即是多”,鼓勵用簡單的原語組合解決問題,天然地抵制不必要的復雜性。
- 強大的標準庫: Go 提供了功能豐富且高質量的標準庫,覆蓋了網絡、并發、加解密、I/O 等眾多領域,減少了對外部特性庫的依賴。很多時候,“自己動手,豐衣足食”(使用標準庫)比引入一個龐大的外部框架更符合Go的風格。
- 關注工程效率: Go的設計目標之一是提高軟件開發(尤其是大型項目)的工程效率和可維護性,這促使Go社區更關注代碼的清晰度和長期成本。
注:技術層面包括語言、工具以及設計思路和方法。
根源二:分層 (Layering) —— 在錯誤的層級“打補丁”
圖片
Pike 認為,現代軟件層層疊加(硬件 -> 內核 -> 運行時 -> 框架 -> 應用代碼),當出現問題時,我們太容易在更高的層級通過包裝(wrap)來“修復”問題,而不是深入底層真正解決它。這導致了層層疊疊的“創可貼”,增加了復雜性和維護難度。他列舉了ChromeOS文件App的例子,并強調要在正確的層級實現功能和修復。
在HN的討論中,有開發者描述的修改按鈕顏色需要穿透17個文件和多個抽象層的例子,正是這種“錯誤分層”或“過度抽象”的生動體現。
技術層面:Go的“解藥”在哪?
- 小接口哲學: Go 鼓勵定義小而專注的接口,這使得組件之間的依賴更清晰、更松耦合。當問題出現時,更容易定位到具體的接口實現層去修復,而不是在外部層層包裝。
- 組合優于繼承: Go 通過組合(struct embedding)而非繼承來實現代碼復用,避免了深度繼承帶來的復雜性和脆弱性,使得在“正確層級”修改代碼更易操作。
- 顯式錯誤處理: if err != nil 的模式強制開發者在調用點處理錯誤,使得問題更難被“隱藏”到上層去統一“包裝”處理,鼓勵在錯誤發生的源頭附近解決或添加上下文。
根源三:依賴 (Dependencies) —— 看不見的“冰山”
圖片
這是Pike演講中著墨最多、也最為憂慮的一點。他用數據(NPM 包平均依賴 115 個其他包,每天 1/4 的依賴解析發生變化)和實例(Kubernetes 的復雜依賴圖)強調:
- 現代軟件依賴數量驚人且變化極快。
- 我們幾乎不可能完全理解自己項目的所有直接和間接依賴。
- 依賴中隱藏著巨大的維護成本、Bug 和安全風險。
- 簡單的 npm update 或 audit 無法解決根本問題。
他強烈建議要理解依賴的成本,嚴格、定期地審視依賴樹,并推薦了 deps.dev 這樣的工具。
HN 社區對此深有同感,紛紛吐槽“為了一個函數引入整個庫”、“脆弱的傳遞性依賴”、“供應鏈安全”等問題,并呼喚更好的依賴分析工具。
技術層面:Go的“解藥”在哪?
- Go Modules: 相比 NPM 等包管理器,Go Modules 提供了相對更好的依賴管理機制,包括語義化版本控制、go.sum 校驗和、最小版本選擇 (MVS) 等,提高了依賴的可預測性和安全性,但也要注意Go module并非完美。
- 強大的標準庫: 這是 Go 對抗依賴泛濫的最有力武器。很多功能可以直接使用標準庫,避免引入外部依賴。
- 社區文化: Go 社區相對而言更推崇穩定性和較少的依賴。引入一個大型框架或過多的外部庫在 Go 社區通常需要更充分的理由。
- 工具支持: Go 提供了 go mod graph, go mod why 等命令,可以幫助開發者理解依賴關系。結合 deps.dev,可以在一定程度上實踐 Pike 的建議。
根源四:開源模式 (Open Source Development) —— “大門敞開” vs “嚴格把關”
圖片
Pike 對比了兩種開源開發模式:
- “真正的開源方式” (The true open source way): 接受一切貢獻 (Accept everything that comes)。他認為這是膨脹和 Bug 的巨大來源。
- 更好的方式: 設立嚴格的代碼質量、標準、評審、測試、貢獻者審查等“門檻”,對允許合入的內容有標準。這種方式維護成本低得多。
他暗示 Go 項目本身更傾向于后者,強調“先做好再提交”(make it good before checking it in)。可能很多Gopher也感受到了這一點,Go項目本身對代碼質量的review非常嚴格,這一定程度上也“延緩”了一些新特性進入Go的時間點。
HN 的討論中也涉及了類似 "Bazaar vs Cathedral" 的模式對比,但觀點更加復雜,認為現實中的項目往往處于兩者之間的某個位置,并且“完全不接受外部貢獻”也并非良策。
技術層面:Go的“解藥”在哪?
- Go 自身的開發模式: Go 語言本身(由 Google 主導)的開發流程相對嚴謹,對代碼質量和向后兼容性有較高要求,可以看作是“嚴格把關”模式的體現。
- 標準庫的設計: Go 標準庫的設計精良、接口穩定,為開發者提供了一個高質量的基礎平臺,減少了對外部“隨意貢獻”的依賴。
- 社區項目實踐: 觀察 Go 社區一些知名的開源項目,其貢獻流程和代碼標準通常也比較嚴格。
反思與現實:Go 也非萬能,“警惕與紀律”仍是關鍵
雖然 Go 的設計哲學和工具鏈在對抗軟件膨脹方面提供了許多“天然優勢”和“解藥”,但我們必須清醒地認識到,Go 語言本身并不能完全免疫膨脹。
正如 Pike 在其“建議”(Advice) 中反復強調的,以及 HN 討論中部分開發者指出的,最終軟件的質量很大程度上取決于**開發者和團隊的“警惕與紀律” (vigilance and discipline)**:
- 我們是否真正理解并避免了增加不相稱成本的特性?
- 我們是否努力在正確的層級解決問題?
- 我們是否審慎地評估和管理了每一個依賴?
- 我們是否堅持了高標準的開發和評審流程?
如果缺乏這些,即使使用 Go,項目同樣可能變得臃腫、復雜和難以維護。同時,HN 討論也提醒我們,軟件膨脹背后還有更深層次的組織、文化和經濟因素,這些往往超出了單純的技術和開發者紀律所能解決的范疇。
小結:擁抱 Go 的簡潔,但需務實前行
Rob Pike 的“抱怨”為我們敲響了警鐘,Hacker News 的熱議則展現了軟件膨脹問題的復雜性和普遍性。它確實是我們在工程實踐中需要持續對抗的“熵增”現象。
Go 語言以其簡潔、顯式、組合的設計哲學,以及強大的標準庫和相對穩健的依賴管理,在技術層面上,為我們提供了對抗膨脹的有力武器。理解并擁抱這些 Go 的“基因”,無疑能在一定程度上幫助我們構建更健康、更可持續的軟件系統。
當然,Pike 的觀點也并非金科玉律。有批評者指出,他的視角可能帶有一定的“NIH(非我發明)傾向”,并且存在兩個關鍵的“盲點”:
- 忽視了“不使用依賴”同樣是巨大的技術債。 每一行自寫的代碼都需要永遠維護。
- 現實中的選擇往往不是“使用依賴 vs 自己實現”,而是“使用依賴 vs 根本不做這個功能”。 面對復雜的合規要求(如 ADA、GDPR)、第三方集成或 FIPS 認證等,從零開始構建的成本(可能需要數百人年)往往讓“自己實現”變得不切實際。為了讓產品能夠及時上線并滿足用戶(哪怕是 Pike 本人可能也在使用的“緩慢”網站)的需求,引入依賴和一定的“膨脹”有時是必要且務實的選擇。
注:“NIH(非我發明)傾向”是一種心理現象,指的是人們對他人提出的想法或創新持有偏見,通常因為這些想法不是自己發明的。這種傾向使得人們傾向于低估或拒絕其他人的創意,盡管這些創意可能是有價值的。
這種批評也提醒了我們,雖然 Pike 對簡潔和紀律的呼吁值得我們高度重視,但在真實的商業環境和復雜的工程約束下,我們必須做出務實的權衡。純粹的技術理想有時需要向現實妥協。
最終,我們每一位 Gopher 都需要在理解 Go 簡潔之道的同時,保持批判性思維和務實態度。 在日常的每一個決策中,審慎地權衡簡單與復雜、理想與現實、引入依賴與自主掌控,才能在這場與“膨脹”的持久戰中,找到最適合我們項目和團隊的平衡點,交付真正有價值且可持續的軟件。
你如何看待 Rob Pike 對軟件膨脹的觀點?你認為他的批評切中要害,還是忽視了現實的復雜性?歡迎在評論區分享你的思考與實踐!
參考資料
[1] Rob Pike - On Bloat: https://docs.google.com/presentation/d/e/2PACX-1vSmIbSwh1_DXKEMU5YKgYpt5_b4yfOfpfEOKS5_cvtLdiHsX6zt-gNeisamRuCtDtCb2SbTafTI8V47/pub?slide=id.p
[2] HN:On Bloat: https://news.ycombinator.com/item?id=43045713
[3] Pike is wrong on bloat: https://blog.habets.se/2025/02/Pike-is-wrong-on-bloat.html
[4] On Bloat: https://commandcenter.blogspot.com/2025/02/on-bloat-these-are-slides-from-talk-i.html