10.3 阿蘭·凱的遺憾:為什麼現代 OOP 偏離了他最初「訊息傳遞」的核心哲學?#
「我發明了『物件導向』這個詞,但它被理解錯了」#
Kay 晚年在演講與郵件列表中反覆表達一個近乎悲傷的主張:
「我發明了物件導向這個術語,但我沒有把 C++/Java 算進來。」
他列舉的偏離清單:
- 繼承被奉為核心:Kay 認為繼承只是實現細節。繼承的深層問題(脆弱基類、菱形繼承)在 1990s 已被工程界充分認識——組合優於繼承成為新共識,Go 語言甚至完全刪除繼承(只有介面組合)
- 資料+方法的捆綁成為定義:這把 OOP 降格為「程式碼組織術」,丟掉了「自治單元協作」的系統觀
- 類別成為必需品:Smalltalk 中類別只是便捷工具,物件才是本體——JavaScript 1995 年反而是更接近 Kay 原意的實現(prototype 思想,13.1 伏筆)
為什麼偏離發生了:三種歷史力量#
1. C++ 的路徑依賴。Stroustrup 的設計約束是「與 C 相容 + 零額外開銷」(11 章)——在這個約束下,訊息傳遞的動態派發必須打折(虛函式表是折衷)。工程約束決定哲學的稀釋程度。
2. 教育的簡化傳播。「封裝、繼承、多型」三件套的教科書化讓 OOP 成為可批量考試的知識——思想被壓縮為考點。UML(1990s)的興起把 OOP 進一步「圖表化」。
3. 企業 IT 的收編。Java(1995)把 OOP 變成企業開發的標準流程(J2EE 的層層抽象工廠)——當範式成為大型組織的行政標準,它必然官僚化。Kay 諷刺過的「CORBA 與設計模式軍備競賽」,本質是組織複雜性在語法層的投影。
偏離的代價與反撲#
諷刺的是,OOP 官僚化的代價在 2010s 集中爆發:
- 深度繼承層級的可維護性災難(Java 企業系統的經典病)
- 共享可變狀態的並發地獄——多核時代(2005+)後,「萬物皆可變物件」與並行天然衝突
- 反撲的形態:
- 函數式回潮:不可變資料、純函數(React 2013、Rust、Clojure)
- 訊息傳遞的正名:Go 的 channel(CSP)、Actor 框架、微服務(服務就是大型物件,HTTP 就是訊息——Kay 的生物學在系統架構層復活)
- 資料導向設計:遊戲業(ECS 架構)公開拋棄 OOP 的效能包袱
Kay 的思想沒有輸,它只是換了宿主——從「類別語法」遷移到了「系統架構與並發模型」。
Kay 對程式教育與未來的持續呼籲#
Kay 晚年(VPRI 研究所,2001–2018)致力於兩件事:
1. 重新發明程式設計教育:STEPS 專案——目標:用一萬行代碼重寫整個個人計算系統,證明今日軟體膨脹是不必要的。他們的演示(HTML + TCP + 編譯器在數百行內實現)是對「複雜性熵增」的正面挑戰。「軟體為什麼這麼大」是 Kay 一生的追問——他認為當代軟體的臃腫是文化失敗(沒有動機做減法),而非技術必然
2. 「自然語言級」程式設計的探索:Kay 一直認為真正的目標是讓孩子用「造」的方式理解世界。Etoys、Scratch(MIT,2007——Smalltalk 教學傳統的直接繼承者,積木式編程)是這條線的成品。Scratch 的數億兒童用戶,是 Dynabook 願景五十年後的遲到收成。
歷史的天平:Kay 錯了嗎?#
Kay 對的地方: - 訊息傳遞確實是分散式系統的正解(微服務、Actor、事件溯源) - 「軟體應像生物般成長」的願景,在熱重載、容器編排、活體文檔中部分實現 - 程式設計應普及為「素養」而非「職業技能」——AI 時代(17 章)這個主張更顯預見性
現實對 Kay 的修正: - 大規模協作需要剛性契約(型別、介面、編譯期檢查)——Smalltalk 的全動態在小團隊是天堂,在千人協作是地獄(Java 的強型別正是對此的回應) - 硬體經濟學長期懲罰純訊息傳遞架構,直到 2010s 才鬆綁
結論:Smalltalk 不是失敗的語言,而是超前的系統哲學。它的核心洞見(自治單元+訊息)在硬體與組織條件成熟後,以分散式系統的形式成為主流。範式的壽命不以語言的生死計。
小結#
| Kay 的原意 | 主流 OOP 的走向 | 2020s 的回歸 |
|---|---|---|
| 訊息傳遞 | 函數呼叫 | 微服務、Actor、事件驅動 |
| 物件=自治單元 | 物件=資料+方法 | 容器、服務實例 |
| 反對繼承中心 | 繼承為核心 | 組合優先、Go 去繼承 |
| 活體系統 | 編譯期靜態 | 熱重載、可觀測性、LLM 互動開發 |
| Dynabook | 消費家電 | Scratch、AI 編程助手 |
下一章,我們看 OOP 的另一條路線——C++ 如何在「與 C 相容、零開銷」的鐵約束下,把物件範式做了工程化的最大妥協。