「這就是 Unix 哲學:寫只做一件事並做好的程式;讓程式彼此能合作;讓程式能處理文字串流,因為那是通用介面。」——道格拉斯・麥克羅伊(Douglas McIlroy)
Unix 為什麼重要#
Unix 是一套設計哲學,啟發了今日大多數作業系統:Linux、macOS 都是它的後裔。
- 約 7 成的 Web Server 跑在 Linux
- 大多數超級電腦使用 Unix
- macOS 是註冊認證的 Unix 系統
**DOTADIW(Do One Thing And Do It Well)**就是讓 Linus Torvalds、Ken Thompson、Brian Kernighan 等世界級工程師能合作出數百萬行程式碼的關鍵。
哲學總覽#
Unix 哲學要求簡單、清楚、模組化、易於擴展的程式碼。寧可可組合(composable),不要單體(monolithic)。
舉例:寫個 url_to_html(url),它應該只做「拿 HTML、回傳字串」這一件事:
def url_to_html(url):
return urllib.request.urlopen(url).read()別在裡面加修補標籤、美化 HTML 等功能——那是另一個函式 prettify_html() 該做的事。
15 條 Unix 原則#
作者整理自 Eric Raymond 與 Mike Gancarz,並用 Python 範例說明。
1. 每個函式只做好一件事#
把 display_html(url) 拆成多個小函式(取 HTML、補標籤、美化),透過**管線(piping)**串接:
def display_html(url):
html = url_to_html(url)
fixed = fix_missing_tags(html)
return prettify_html(fixed)每個函式都可獨立重用、獨立測試、獨立修改。

Figure 7-1: 多個各自做好一件事的小函式,組合出更大的功能。
2. 簡單勝過複雜#
Python 的 Zen 在 shell 輸入 import this 即可看到:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
...3. 小即是美#
寫小函式、自己當建築師串接它們。三個理由:
- 降低複雜度:人腦能同時掌握的資訊有限
- 提升可維護性:小變動不易產生全域副作用
- 提升可測試性:單元測試對小函式才有意義
Python 標準函式庫本身就是「小即是美」的範例:很多函式庫不預設安裝,需要時再 import。CORBA、SOA、microservices 等架構都是同一精神的延伸——小、可獨立部署、可被多程式重用。
4. 盡早建立原型#
呼應第 3 章 MVP。Finxter 的真正 MVP 應該只是一張社群媒體上的程式謎題圖片——那才足以驗證「使用者是否願意解 puzzle」。Fail early, fail often, fail forward.

Figure 7-2: Finxter.com app 與 Finxter MVP 的對比。
5. 可攜性勝於效率#
可攜性(portability)讓程式跨環境運作。虛擬化(virtualization)就是經典例子:多一層虛擬化犧牲效能、換來「幾乎任何硬體都能跑」。
Web 應用要在 macOS、Windows、Linux 的瀏覽器都能跑——使用者的時間、人命、無障礙存取,遠比 CPU 週期珍貴。
範例對比:
# 不夠可攜
import numpy as np
def calculate_average_age(*args):
a = np.array(args)
return np.average(a)# 更可攜:命名通用、不需外部函式庫
def average(*args):
return sum(args) / len(args)6. 用扁平文字檔案儲存資料#
CSV 等扁平文字檔的優點:
- 任何文字編輯器可開啟
- 人類可讀
- 容易分享與手動修改
代價是效率不佳。資料庫的特殊格式可以索引、壓縮、低延遲存取,但只在效能真的關鍵時才用(例如 Google 搜尋)。一個跑 10,000 筆機器學習資料的小腳本,CSV 完全足夠。
7. 善用軟體槓桿#
槓桿(leverage)就是用小力換大果:
- 集體智慧:用函式庫而非從零實作;用 StackOverflow;請人 review
- 計算力:機器比人快又便宜
範例:用 re(正則表達式)一行解網頁連結分析:
practice_tests = re.findall(r"(<a.*?finxter.*?(test|puzzle).*?>)", page)import 的那一刻,你就用上了千行優化的程式碼。
8. 避免「占用式」使用者介面#
**占用式介面(captive user interface)**強迫使用者互動才能繼續執行(如 SSH、vim、Python 的 input())。問題是,這把功能與互動黏在一起。
# 不好:互動與計算耦合
def your_life_expectancy():
age = int(input('how old are you? '))
if age < 85:
exp_years = 72 - 0.8 * age
else:
exp_years = 22 - 0.2 * age
print(...)# 好:把使用者介面分離出來
def your_life_expectancy(age):
if age < 85:
return 72 - 0.8 * age
return 22 - 0.2 * age分離後,這個函式可被批次處理、可被繪圖、可被任何呼叫者使用——直接拿來畫 0–99 歲的折線圖也沒問題。

Figure 7-3: 用 0–99 歲跑這套啟發式得到的生命期望折線圖。
9. 把每個程式都當作 filter#
filter 是「把輸入轉成輸出」的函式。設計時遵循:
- 同質輸入/輸出(homogeneous I/O mapping):函式輸入 = 函式回傳;檔案進 = 檔案出;stdin 進 = stdout 出。
- 不要在函式內部
print,應該return字串,由呼叫者決定 print、寫檔還是傳給下一個函式。
10. 更糟的反而更好(Worse Is Better)#
由 LISP 開發者 Richard Gabriel 提出。資源有限時,先推一個比較粗糙的版本,搶占第一個進場優勢——比起等到完美再上線,更能取得回饋與動能。
別誤解:這不是說品質越糟越好。有無限資源時當然要做完美。 但現實有限,第一名往往不是最好的,而是最先抵達的。
11. 乾淨勝過聰明#
對比兩個 bubble sort:
# 乾淨
def bubblesort(l):
for boundary in range(len(l)-1, 0, -1):
for i in range(boundary):
if l[i] > l[i+1]:
l[i], l[i+1] = l[i+1], l[i]
return l# 「聰明」(用條件運算式縮成一行)
l[i], l[i+1] = (l[i+1], l[i]) if l[i] > l[i+1] else (l[i], l[i+1])省了一行,可讀性卻變差。炫技不該以可讀性為代價。
12. 設計可串接的程式#
程式不是孤島。遵循原則 9(filter 設計),自然就有適合的 API。好工程師既是工匠也是建築師——把舊函式、新函式、別人的函式組合出新的東西,介面是設計的核心。
13. 讓程式更穩健#
兩個視角:
程式設計師視角:
- 大型單體 + 全員可改 = 一處錯全死
- Google、Netflix 透過審核流程、測試、權限控制保護程式碼
- 用 Git 等版本控制
- 定期備份資料(資料不在版本控制裡)
- 分散式部署:5 台機器各 1% 故障率,全部同時掛掉是 0.00000001%
使用者視角:
假設使用者是「一群猩猩亂砸鍵盤」+「最高超的駭客在找漏洞」。未處理的例外不只是 bug——還可能是駭客進入主機的立足點。
用單元測試覆蓋邊界情境(負數、零、空輸入)。
14. 能修就修,但要早早大聲失敗#
別把錯誤藏起來——隱藏的錯誤會像複利一樣累積。
語音辨識把兩個完全不同的波形對應到同一個英文字,是訓練資料錯誤。

Figure 7-4: 訓練階段把兩個不同的聲波對應到同一個英文字——錯誤的源頭。
應該:
def classify(wave):
word = wave_to_word(wave)
if duplicate_check(wave, word):
raise ClassificationError('Not Understood')
return word寧可使用者短暫不爽,也不要留下隨機猜測的炸彈。Fail early and noisily.
15. 避免手刻——讓程式去寫程式#
可自動產生的就自動產生。例子:
- 編譯器把高階語言轉成機器碼——讓人類專注於邏輯
- 程式碼產生器(codegen)
- 機器學習:模型本身就是「會自我重寫的程式」,根據資料調整自己直到最大化適應度函式(fitness function)
編譯器沒有取代程式設計師——反而開啟了更廣的應用世界。機器學習可能會走同樣的路:工程師不再寫低階細節,而是把不同模型像積木一樣組合起來。
結論#
15 條原則一口氣回顧:
- 每個函式只做好一件事
- 簡單勝過複雜
- 小即是美
- 盡早建立原型
- 可攜性勝於效率
- 用扁平文字檔案儲存資料
- 善用軟體槓桿
- 避免占用式介面
- 把每個程式都當作 filter
- 更糟的反而更好
- 乾淨勝過聰明
- 設計可串接的程式
- 讓程式更穩健
- 能修就修,但要早早大聲失敗
- 寫程式去寫程式
下一章將進入設計領域的極簡主義——少即是多。