對日常工作的程式設計師而言,為什麼、以及如何運用函數式編程?Uncle Bob 刻意略過 Monad、範疇論這些理論話題,改聚焦於「結構與設計層面的差異」——同一個系統用 OO 與 FP 各寫一遍,會長得多不一樣?他選 Clojure(而非 Haskell)作示範,理由是「語意豐富、語法極簡」,並主張 OO 與 FP 完全相容、優秀工程師應同時運用。
🧠 Core Ideas
- 不可變性(Immutability)是起點。函數式程式「沒有變數」——狀態只能誕生、不會被改寫。少了賦值,就少了一整類「某處偷偷改了共享狀態」的 Bug。
- 持久性資料靠結構共享。既然不能改,每次「修改」豈不是要複製整個結構?太貴。函數式用結構共享(structural sharing)讓新舊版本共用未變動的部分,兼顧不可變與效能。
- 沒有賦值,就用遞迴表達迴圈。在沒有可變計數器的世界裡,遞迴取代 for 迴圈;尾呼叫優化(TCO)避免堆疊爆炸。
- 惰性求值(Laziness)。只在真正需要值時才計算,讓無限資料結構與高效組合成為可能。
- 一句話定調全書:「在可變語言中,行為流經物件;在函式式語言中,物件流經行為。」函數式程式更像水管系統——資料穿過一連串純函式被逐步轉換。
- SOLID 在函數式世界依然適用。這套原則關心的是「模組與依賴」,而非「類別」這個語言特性;設計模式(GOF)也不是 OO 專利,在 Clojure 裡有對應寫法。
TIP
別被「函式式即天然並發安全」的口號誤導。Uncle Bob 明確反直覺地指出:函數式並不能讓多執行緒「自動安全」於競態條件——它消除的是「共享可變狀態」這一大類問題,但真實世界的 I/O、時間、外部狀態仍需要在受控、明確的範圍內處理。這也是本書第一部把「狀態管理」刻意排在最後一章的原因。
⚖️ 為什麼「禁慾 → 放鬆」的順序很重要
本書第一部五章的順序是刻意安排的:先建立「沒有變數」的最嚴格紀律,再一步步引進現實世界的妥協。這個順序本身就是一種教學設計。
先禁慾,才能分辨兩種可變性
-
先禁慾。第一步強制「完全不可變」,讓讀者親身體會純函數的世界長什麼樣——哪些程式碼結構會浮現、哪些會消失。
-
再放鬆。接著才引進持久性資料、遞迴、惰性求值,最後才談狀態管理與 I/O——這些是對現實世界不得不做的妥協。
-
關鍵收穫:走完這個順序,讀者才能清楚分辨「哪些是可以避免的可變性(該消除),哪些是必須面對的可變性(該隔離)」。這個判斷力,正是函數式設計帶給 OO 工程師最實用的東西。
🖼️ 一本寫給 OO 老將的跨典範橋接書
這本書的獨特定位,是由一位在 OO/SOLID 戰壕裡打了一輩子的老將,寫給同樣背景的讀者。多數函數式入門書面向「已被 FP 哲學說服」的人;Uncle Bob 則用讀者早已熟悉的 SOLID、TDD、設計模式詞彙當腳手架,帶 OO 工程師「初次認真看待 FP」。
方法論的核心是第二部的「對照分析」:把質因數分解、保齡球計分、薪資系統等練習題,用 Java(OO)與 Clojure(FP)各寫一遍,全程以 TDD 驅動,逐步呈現結構如何在紅綠循環中長出來。第三部再把焦點從「比較」轉到「設計」,用「物件流經行為」的視角重新詮釋 SOLID。最後以 Wa-Tor(捕食者—獵物細胞自動機)收束——刻意把一支數小時可 hack 完的小遊戲,當成 5,000 萬行企業級應用來架構,演練邊界、依賴反轉、Factory Method。這正是它與《Clean Code》一脈相承之處:不可變與無副作用,本質上是「函式只做一件事、不留副作用」這條紀律推到語言典範層次的極致。
IMPORTANT
本書真正的主張不是「FP 比 OO 好」,而是「兩者相容,各有適用場景」。不可變與純函數消除了一整類狀態相關的 Bug,讓程式更容易推理與測試;但它不是銀彈,真實世界的副作用仍需被明確隔離。把可避免的可變性消除、把必須面對的可變性隔離——這才是函數式設計送給每位工程師的核心紀律。
🔑 Takeaways
- 函數式的核心是不可變與無副作用:狀態只誕生、不改寫,消除一整類共享狀態 Bug。
- 持久性資料靠結構共享、迴圈靠遞迴+TCO、計算靠惰性求值。
- 記住定調句:可變語言中行為流經物件,函式式語言中物件流經行為。
- FP 不會讓多執行緒自動安全;真實世界的 I/O 與時間仍需受控隔離。
- 延伸:SOLID 關心的是模組與依賴、跨典範皆適用,見 SOLID:五大設計原則。
No notes yet — jot your takeaways or Q&A here.