工程哲學:Thompson 與 Ritchie,把一件事做到極致

重點摘要
- 小而銳利的工具。 每個程式只把一件事做好,並抗拒去做第二件事;有了新需求,就做一個新工具,而不是再加一個旗標。
- 組合勝過功能。 力量來自於透過通用的文字介面——管道——把程式串接起來,能力因此在接縫處浮現,而不在任何單一程式之內。「把一件事做好」這句經典之言出自 Doug McIlroy,而非 Thompson 或 Ritchie。
- 以 C 達成可攜性。 用 C 重寫 Unix,讓系統得以移植到新硬體——只需移植一個編譯器,而非重寫整個系統——這正是 Unix 能無處不在的主因。
- 不要信任不是你親手打造的東西。 Thompson 的〈Reflections on Trusting Trust〉指出,後門可以藏在二進位檔裡,而在你所能檢視的任何原始碼中都不留痕跡——這是供應鏈安全的奠基洞見。
核心原則
「撰寫只做一件事、並把它做好的程式。撰寫能彼此協作的程式。撰寫能處理文字串流的程式,因為那是一個通用介面。」——Doug McIlroy,總結 Unix 哲學1
這句話既非出自 Thompson,也非出自 Ritchie。它是由 Doug McIlroy 寫下的——他是兩人在貝爾實驗室的同事,也是發明 Unix 管道的人——出現在他為 1978 年《Bell System Technical Journal》特刊所寫的前言裡。1但這句話卻是對 Thompson 與 Ritchie 實際打造之物最乾淨俐落的陳述;而之所以選擇以它開場、而非以兩人各自的某句話起頭,本身就是重點所在:Unix 哲學從來不是某位天才獨力撰寫的宣言。它是一種文化,而那文化本身就是成品。
這項原則有三個動作,而它們密不可分。讓每個工具小而銳利——只做一份工作、把它做好,毫無做第二件事的野心。讓工具可以組合——前一個的輸出就是後一個的輸入,於是能力來自組合,而非來自任何程式長成龐然大物。並讓它們之間的介面通用化——純文字,如此任何工具都能與任何其他工具串接,而彼此根本不需知道對方存在。力量住在接縫裡,不在零件中。一個排序文字行的程式對網站日誌一無所知;一個計算重複項的程式對 HTTP 狀態碼一無所知;以管道串接起來,它們卻能回答任一程式都不是為此而生的問題。
這與催生大多數軟體的本能恰恰相反。自然的拉力是讓一個程式做更多——加個旗標、加個模式、把下一個需求摺進你手上已有的東西裡。McIlroy 的第一條規則點名了這股拉力並予以拒絕:「要完成新工作,就重新打造,而不要靠添加新『功能』來把舊程式複雜化。」1Thompson 與 Ritchie 的整套系統,正是簡潔是一切其他事物的前提、以及組合——而非功能——才是小東西變強大之道的明證。
背景脈絡
Unix 誕生於一場失敗。整個 1960 年代中期,貝爾實驗室與 MIT、奇異公司合作開發 Multics,一套野心極大的分時作業系統,意圖幾乎無所不能。到了 1969 年,它已變得如此複雜、進度如此落後,貝爾實驗室決定退出,而曾參與其中的研究者——Ken Thompson、Dennis Ritchie、Doug McIlroy、Joe Ossanna——只剩下挫折,既失去了一個舒適的互動式運算環境,也對該如何「不」去打造一套系統有了強烈的體悟。2

Ken Thompson 於 1943 年 2 月 4 日生於紐奧良,在加州大學柏克萊分校取得電機工程與電腦科學的學士與碩士學位後,於 1966 年加入貝爾實驗室。3Dennis Ritchie 於 1941 年 9 月 9 日生於紐約州的 Bronxville,1967 年加入運算科學研究中心。41969 年,Thompson 找到一台被棄置的 PDP-7——一台小型、當時已過時的迷你電腦——並開始在上頭打造一套微型作業系統,部分原因是為了執行他寫的一款名為《Space Travel》的遊戲。Thompson 後來把分工講得很白:「最初兩三個版本的 UNIX 全是我一個人做的。而 Dennis 成了傳道者。」3第一版是以 PDP-7 組合語言寫成的。
這名字源於一個玩笑。Multics 代表「多工」(Multiplexed),而新系統刻意做得小巧,於是這群人把它叫做「UNICS」——Uniplexed Information and Computing Service——藉此調侃 Multics。拼法後來漂移成「Unix」,而通常被認為是命名者的 Brian Kernighan 後來指出,沒有人能確切記得最終形式究竟是怎麼來的。2這份小巧並非偶然,也不是一個有待長大後擺脫的侷限。它就是設計本身。
成就
Unix 與檔案系統
Unix 第一件做對的事,是對「電腦資源究竟是什麼」提出了一套模型。早期系統把檔案、裝置與通訊管道當成不同種類的東西,各有各的特殊介面。Unix 把它們收攏為一。它呈現出單一的階層式檔案系統——一棵目錄組成的樹——然後把幾乎所有東西都當成其中的一個檔案:不只是文件,連裝置以及行程間通訊管道也是如此。2一個能讀寫檔案的程式,無需任何改動,就能去讀終端機、磁帶機,或另一個程式,因為對該程式而言,它們全都只是檔案。
這就是通用介面最初的形態。「一切皆檔案」意味著一個小工具不需要為每一種輸入準備一個不同的版本;它只需要一個。組合的成本因此趨近於零,因為每個元件原本就說著同一種語言。階層式檔案系統,以及一致的 open/read/write/close 介面,正是讓哲學的其餘部分得以成立的根本:你無法組合那些各自要求一個量身打造接頭的工具。
C 與可攜性
第二項突破是讓系統可攜,而這需要一種語言。Ritchie 在 1969 至 1973 年間創造了 C,由 Thompson 的 B 語言演化而來,而 B 又承襲自 BCPL。4B 是無型別且採直譯的;C 加入了資料型別與結構,並編譯成高效的機器碼,既貼近硬體到足以拿來寫作業系統,又抽象到足以在機器之間移植。
決定性的時刻出現在約 1973 年,當時第 4 版 Unix 以 C 重寫。2在那之前,作業系統就是組合語言,永久焊死在它所寫就的那一台機器上。用高階語言重寫 Unix 近乎異端——傳統智慧認為系統程式碼非得是手工調校的組合語言不可,否則就會太慢。Thompson 與 Ritchie 還是做了,而回報就是可攜性:Unix 如今能移植到新硬體,只需移植一個編譯器,而非重寫整個系統。光是那一個決定,就是 Unix 能蔓延到運算每一個角落、而同時代的對手卻仍被栓死在原本那塊鐵皮上的主要原因。1978 年,Ritchie 與 Kernighan 出版了《The C Programming Language》——也就是「K&R」——這本精簡而精確的書教會了一整個世代寫 C,至今仍是技術文筆的典範。5Thompson 與 Ritchie 則在 1974 年 7 月的《Communications of the ACM》論文〈The UNIX Time-Sharing System〉中,向更廣的世界宣告了這套系統本身。6
管道與組合模型

如果說檔案系統讓工具說起同一種語言,那麼管道就讓它們彼此交談。這個想法出自 Doug McIlroy:多年來他一直主張要有一種把程式首尾相連的方式,讓前一個的輸出直接流入下一個,就像一段段的花園水管。Thompson 在 1973 年將它實作出來——據說只花了一個晚上——為 shell 加入了 pipe() 系統呼叫與 | 運算子。7McIlroy 描述了接下來發生的事:「隔天就上演了一場令人難忘的單行指令狂歡,每個人都加入這場接管配水的興奮裡。」7
那場單行指令的狂歡,「正是」哲學的實際運作。沒有人需要寫一個新程式;他們發現,自己手上原本就有的那些小程式,可以串接起來去回答任何一個都不曾為之設計的問題。一條像是 grep 接 cut 接 sort 接 uniq -c 接 sort -rn 接 head 的管線,由六個階段構成,每一段都不知道其他段的存在,每一段只做一件事,透過一道文字串流由左至右組合起來。能力是浮現出來的。它住在 | 裡,而不在任何單一指令中。
這是整套系統裡最深刻的構想。大多數軟體靠堆積成長:一個程式把每個新需求吸收進來,直到變成一個只有它的作者才看得懂的龐然大物。Unix 靠組合成長:系統始終是一套小零件的工具箱,而新能力來自舊零件的新排列組合。文字串流就是那個讓排列組合變得免費的通用介面。這正是為什麼一個 Unix shell 在五十年後,依然是現存最具表達力的程式設計環境之一——不是儘管它由微小的單一用途程式組成,而正是因為如此。
信任的信任,與後續的影響
1983 年,Thompson 與 Ritchie 共同獲頒 ACM 圖靈獎。引文寫道「表彰他們發展通用作業系統理論,特別是 UNIX 作業系統的實作」,而委員會的聲明精確地點出了那項原則:「UNIX 系統的成功,源於它對少數幾個關鍵構想品味十足的取捨,以及它們優雅的實作。」8對少數幾個關鍵構想品味十足的取捨——這座獎,實質上是為「克制」而頒。
Thompson 自己的圖靈獎演說,於 1984 年以〈Reflections on Trusting Trust〉發表,把同樣的極簡嚴謹轉向了安全領域。他示範了,可以教一個編譯器把後門插進 login 程式裡,並把這個「插入後門」的動作再插進它日後所編譯的任何編譯器中——如此一來,惡意程式碼只活在二進位檔裡,而在你所能檢視的任何原始碼中都不留痕跡。他的結論是運算史上最常被引用的句子之一:「你無法信任不是你完全親手打造的程式碼……再多的原始碼層級驗證或審查,都無法保護你免於使用不受信任的程式碼。」9這是供應鏈安全思維的奠基文獻——也就是體認到,你所信任的並非原始碼,而是產出那個二進位檔的整條工具鏈。
兩人後來的職涯延續了同樣的直覺。Thompson 始終不安於現狀:在貝爾實驗室,他打造了《Plan 9》作業系統(把「一切皆檔案」推得更遠,跨越了網路)、《ed》編輯器,以及正規表示式與《grep》的實用理論。1992 年,他和 Rob Pike 在一個晚上設計出 UTF-8——這種如今承載著世上幾乎所有文字的變動寬度文字編碼——據說還是畫在一張餐墊紙上。3而到了 2007 年,在 Google,Thompson 與 Robert Griesemer、Rob Pike 共同設計了 Go 程式語言,並於 2009 年公開發表:一種刻意做得小巧、編譯快速、可組合的語言,讀來像是對 Unix 價值有意識的回歸。10Ritchie 於 2011 年 10 月 12 日逝世,留下的印記較為安靜,卻更為無所不在;正如歷史學家 Paul Ceruzzi 所言:「假如你有一台顯微鏡,能看進一台電腦裡,你會看到他的成果遍布其中。」4
方法
這套方法在四十年間、在兩個鮮少需要解釋它的人身上,始終如一。
打造小而銳利的工具。 每個程式只做一份工作。所需的紀律是拒絕:當新需求出現,答案是一個新工具,而不是在舊工具上栓一個新旗標。「重新打造,而不要把舊程式複雜化。」1
組合,而非堆積。 能力應當從組合中浮現。當一套系統是一組小零件的工具箱、靠重新排列而非靠任何一塊零件膨脹成龐然大物來成長時,它才能保持可理解。
標準化介面,而非工具。 那個統合的動作——「一切皆檔案」、程式之間流動的純文字串流——是讓「連結」通用化,好讓「元件」能對彼此保持無知。廉價的接縫,正是讓小零件變強大的關鍵。
有品味地選擇少數幾個關鍵構想。 圖靈獎委員會的措辭並非客套;它就是方法本身。Unix 因它捨棄了什麼而著稱。透過 C 達成的可攜性、檔案抽象、管道——寥寥幾個決定,每一個都承載著巨大的份量,而雜亂則被刻意排除在外。
不信任你無法檢視之物。 〈Trusting Trust〉是這套方法朝內瞄準的版本:簡潔與可讀不只是美學上的美德,更是信任唯一真實的基礎,因為複雜正是那些你看不見的東西得以藏身之處。
影響鏈
是誰形塑了他們
Multics,作為反面教材。 最具形塑力的單一影響,是一套他們協助打造、隨後抽身離開的系統。Multics 以最昂貴的方式教會了 Thompson 與 Ritchie,野心過大要付出什麼代價——而 Unix 在很大程度上就是對它的一場有紀律的反動。(形塑性影響)
Doug McIlroy。 身為運算科學研究中心的主管,McIlroy 發明了管道,以文字闡述了「把一件事做好」的哲學,並扮演這個團隊不留情面的品味批判者。組合模型有他的一份,不亞於任何人;對於這套哲學的經典陳述,他才是正確的歸屬。(直接影響)
貝爾實驗室的研究文化。 一小群同儕,被賦予自由與好機器,彼此之間以優雅為優化目標,而非為了一張產品藍圖。Unix 不是由管理層規格化出來的;它是從一種重視品味、嘲笑臃腫的文化中堆積而成的。(形塑性影響)
是他們形塑了誰
每一個 Unix 的後裔。 Linux、各種 BSD 與 macOS 都是直系繼承者;Thompson 與 Ritchie 在一台被棄置的 PDP-7 上寫出的系統,如今執行著地球上大多數的伺服器、手機與嵌入式裝置。
每一個 shell 與命令列。 管道與組合模型,是基本上每一位程式設計師與系統管理員五十年來日常的工作環境——其精髓未曾改變,因為那精髓本就是對的。
C 及其子嗣。 C 成了系統程式設計的通用語,它的語法與語意迴響於 C++、Java、Go、Rust,以及今日所寫的大半程式之中。K&R 至今仍是「該如何為一種語言撰寫文件」的範本。
Unix 哲學本身。 「把一件事做好」超越了 Unix,成為一條通用的設計原則——適用於微服務、命令列工具、那套無建置、由小零件構成的網頁取徑,以及該如何讓 AI 系統保持夠小、好讓它仍然安全且可讀。
貫穿的主線
Thompson 與 Ritchie 是貫穿這個系列那同一份信念在系統層級的表現。Edsger Dijkstra主張簡潔是可靠的前提;Unix 就是那項主張被編譯並出貨的成品——一個由少數幾個關鍵構想組成的核心,小到足以信任。Linus Torvalds 的「好品味」——那種讓特例消失的重寫——就是「把一件事做好」落在單一函式之內,而非橫跨一整條管線;而 Torvalds 正是直接在這兩人奠下的基礎上打造了 Linux 與 Git。John Carmack 那快速、簡單的核心,是同一種減法,只是瞄準了硬體的天花板。而松本行弘為人類幸福而設計 Ruby,則是把 Unix 的直覺——可組合、富表達力的小零件——往上帶進了一種高階語言。這條主線可以一句話道盡:力量應當來自透過一個通用介面去組合小而可理解的零件,而不是來自任何單一零件長成龐然大物。(系列橋接)
我從中汲取的
我一直記著的教訓是:介面就是架構。如今當我設計任何東西時——一個代理、一個工具迴圈、一條腳本構成的管線——誘惑總是去把某一個元件變得更聰明,把下一個需求摺進我手上已有的東西裡,直到它變成一個只有我看得懂的龐然大物。Unix 的做法恰恰相反:讓每一塊零件都小到能徹底理解,並把智慧放進零件「如何連接」之中。在一群笨零件之間有一道乾淨、通用的接縫,每一次都勝過一個聰明卻沒有乾淨接縫的零件。這跟品質是唯一的變數是同一套標準——問題從來不是「這一個程式能不能做更多?」而是「這套系統是否仍由我能推理理解的零件構成?」
在我如今所打造的世界裡——AI 代理以工具與文字串接起來——Thompson 與 Ritchie 的設計,以五十多歲的高齡來說,相關得有些不可思議。一個代理是一個小程式;一個工具是一個小程式;讓它們變強大的,是它們之間一道乾淨、通用的介面,而那介面今日大多是結構化的文字。那就是管道,被重新打造了一遍。而〈Trusting Trust〉是我看得最重的那道警告:當一套系統產出程式碼的速度快過任何人所能閱讀時,信任唯一持久的基礎,就是讓零件保持小巧、讓接縫保持可讀,因為複雜正是那些你看不見的東西前去藏身之處。那份信念——品味是一套技術系統、而小巧、可組合、可檢視的零件並非錦上添花,而是整盤遊戲的全部——一路從 1969 年的一台 PDP-7,貫穿到 2026 年的一個代理框架。
常見問題
什麼是 Unix 哲學?
Unix 哲學是一套建立在「小而單一用途的工具透過通用介面組合起來」之上的設計取徑。它最經典的陳述出自 Doug McIlroy,寫於 1978 年:「撰寫只做一件事、並把它做好的程式。撰寫能彼此協作的程式。撰寫能處理文字串流的程式,因為那是一個通用介面。」第一條原則是打造一個新工具,而不是為既有工具添加功能;而系統的力量來自把小零件組合起來——透過管道與純文字——而非來自任何單一程式長成龐然大物。1
Ken Thompson 說過「把一件事做好」嗎?
沒有。「把一件事做好」這句格言以及更廣義的 Unix 哲學,是由貝爾實驗室運算科學研究中心主管 Doug McIlroy 以文字闡述的,出現在他為 1978 年《Bell System Technical Journal》Unix 特刊所寫的前言裡。1Thompson 與 Ritchie 打造了體現這套哲學的系統,而 McIlroy——他同時也發明了 Unix 管道——則是它最清晰的闡述者,以及這個團隊的常駐品味批判者。把這句格言歸給 Thompson,是個常見卻不正確的捷徑。
Thompson 與 Ritchie 究竟創造了什麼?
Ken Thompson 自 1969 年起,在一台 PDP-7 上打造了最初幾版的 Unix 作業系統,後來又創造了 B 語言、《ed》編輯器、實用的正規表示式搜尋(《grep》)、Plan 9 系統、UTF-8(與 Rob Pike 合作),並在 Google 共同設計了 Go。3Dennis Ritchie 創造了 C 程式語言(1969–1973),並用它在 1973 年重寫 Unix 以使其可攜,還在 1978 年與 Brian Kernighan 合著了《The C Programming Language》。45兩人因 Unix 共同獲頒 1983 年的 ACM 圖靈獎。8
〈Reflections on Trusting Trust〉是什麼?
它是 Ken Thompson 1984 年的 ACM 圖靈獎演說,發表於《Communications of the ACM》。他展示了,可以讓一個編譯器把一個隱藏的後門插進某個程式,並在它每次編譯自己的新版本時都重現那個後門——如此一來,惡意程式碼只存在於二進位檔中,在你所能閱讀的任何原始碼裡都不留痕跡。他的結論是:「你無法信任不是你完全親手打造的程式碼……再多的原始碼層級驗證或審查,都無法保護你免於使用不受信任的程式碼。」這是軟體供應鏈安全的一篇奠基文獻。9
參考來源
-
M. Douglas McIlroy,為 “UNIX Time-Sharing System,” The Bell System Technical Journal, Vol. 57, No. 6, Part 2(1978 年 7 月–8 月)所寫的前言。那四點摘要(「讓每個程式把一件事做好……重新打造,而不要靠添加新『功能』來把舊程式複雜化」)以及較簡潔的後續形式:「撰寫只做一件事、並把它做好的程式。撰寫能彼此協作的程式。撰寫能處理文字串流的程式,因為那是一個通用介面。」另見 “Unix philosophy,” Wikipedia。 ↩↩↩↩↩↩
-
“Unix,” Wikipedia。貝爾實驗室於 1969 年放棄 Multics;PDP-7 的起源;「Unics」/「Unix」的命名(Brian Kernighan);第 4 版 Unix 於 1973 年為了可攜性以 C 重寫;階層式檔案系統,以及把裝置與 IPC 當成檔案處理(「一切皆檔案」);管道;1974 年的 CACM 論文。 ↩↩↩↩
-
“Kenneth Lane Thompson,” Wikipedia。1943 年 2 月 4 日生於紐奧良;加州大學柏克萊分校學士/碩士;貝爾實驗室(1966);最初幾版的 Unix(「最初兩三個版本的 UNIX 全是我一個人做的。而 Dennis 成了傳道者。」);B 語言;《ed》、正規表示式、《grep》;Plan 9;與 Rob Pike 合作的 UTF-8(1992);在 Google 的 Go(2007–)。 ↩↩↩↩
-
“Dennis Ritchie,” Wikipedia。1941 年 9 月 9 日生於紐約州 Bronxville;2011 年 10 月 12 日逝世;貝爾實驗室運算科學研究中心(1967);創造了 C(由 B 與 BCPL 演化而來),並用它重寫 Unix 以達成可攜性;Paul Ceruzzi 的引言(「假如你有一台顯微鏡,能看進一台電腦裡,你會看到他的成果遍布其中。」)。 ↩↩↩↩
-
“The C Programming Language,” Wikipedia。Brian Kernighan 與 Dennis Ritchie 合著,1978 年 2 月 22 日首次出版(Prentice Hall);人稱「K&R」;第一本廣為流通的 C 語言書籍。 ↩↩
-
D. M. Ritchie 與 K. Thompson,“The UNIX Time-Sharing System,” Communications of the ACM, Vol. 17, No. 7(1974 年 7 月),pp. 365–375。這篇論文向更廣的運算社群宣告了 Unix。 ↩
-
“Pipeline (Unix),” Wikipedia。管道概念由 Doug McIlroy 構思;由 Ken Thompson 於 1973 年實作(
pipe()系統呼叫與|運算子)。McIlroy:「隔天就上演了一場令人難忘的單行指令狂歡,每個人都加入這場接管配水的興奮裡。」 ↩↩ -
“Dennis M. Ritchie – A.M. Turing Award Laureate,” ACM(鏡像)。1983 年的引文:「表彰他們發展通用作業系統理論,特別是 UNIX 作業系統的實作」;委員會聲明:「UNIX 系統的成功,源於它對少數幾個關鍵構想品味十足的取捨,以及它們優雅的實作。」 ↩↩
-
Ken Thompson,“Reflections on Trusting Trust,” 1984 年 ACM 圖靈獎演說,Communications of the ACM, Vol. 27, No. 8(1984 年 8 月),pp. 761–763。其中的 MORAL 段落:「你無法信任不是你完全親手打造的程式碼。(尤其是來自那些雇用像我這種人的公司的程式碼。)再多的原始碼層級驗證或審查,都無法保護你免於使用不受信任的程式碼。」 ↩↩
-
“Go (programming language),” Wikipedia。「它於 2007 年在 Google 由 Robert Griesemer、Rob Pike 與 Ken Thompson 設計,並於 2009 年 11 月公開發表。」 ↩