這本書寫給誰#
這是一本寫給「在戰壕裡」的程式設計師的書,目標是學會使用函式式程式語言(functional programming language)把真正的事情做出來。作者 Bob 大叔(Robert C. Martin)刻意略過函式式編程在理論層面的話題,例如:
- 單子(Monad)
- 么半群(Monoid)
- 函子(Functor)
- 範疇(Category)
這些理論並非沒有價值,而是對日常工作的程式設計師多半已經被「烤進蛋糕」裡——亦即融入主流語言、函式庫與框架,平時不需直接面對。對函式式理論有興趣的讀者,作者推薦 Mark Seemann 的著作。
本書的核心關懷是:在打造真實系統、服務真實客戶的日常工作中,為什麼以及如何運用函式式編程。書中會反覆對照兩種主流寫法:
- 物件導向語言(如 Java)常見的程式結構
- 函式式語言(如 Clojure)常見的程式結構
選擇 Java 與 Clojure 的理由很實際:Java 普及度高、讀者熟悉;而 Clojure 學起來極為簡單。
函式式與程序式的歷史簡述#
1936 年,兩位數學家——艾倫・圖靈(Alan Turing)與阿隆佐・邱奇(Alonzo Church)——各自獨立解決了大衛・希爾伯特(David Hilbert)提出的「可判定性問題」(The Decidability Problem)。簡言之,他們證明:
- 存在某些整數無法用比自身更小的整數公式計算出來
- 也就是說,有些數字是「不可計算」(uncomputable)的
兩人從不同方向得到同樣結論:
- 圖靈:發明了數位電腦的雛形(圖靈機,Turing machine),證明即使給予無限的時間與空間,仍有些數字無法計算
- 邱奇:發明了 λ 演算(lambda calculus),一種操作函式的數學形式,並證明存在無解的邏輯問題
圖靈與邱奇後來合作證明:圖靈機上的每個程式都能用 λ 演算表示,反之亦然。兩種寫程式的風格在數學上是等價的。
換言之:
- 程序式風格(Turing style):以圖靈機的觀點寫程式
- 函式式風格(Church style):以 λ 演算的觀點寫程式
任何程式都可以用兩種風格之一寫出來。本書要探討的不是這份等價性本身,而是這兩種風格如何影響我們程式的結構與設計——以及這些差異是否在某種意義上有優劣之分。
為什麼選擇 Clojure#
學一門新語言已經很難,要同時學一個新典範更是難上加難。作者選擇 Clojure 是為了把難度降到最低:
- Clojure 語意豐富、語法極簡
- 學習曲線幾乎都落在語意層(函式庫與慣用法),不在語法層
- 換句話說:可以專心學函式式設計,不用花力氣對抗語法
本書並非 Clojure 教程。作者會在前幾章介紹基本知識並透過註腳補充,但仍仰賴讀者自行查閱資料。推薦的速查表:https://clojure.org/api/cheatsheet ↗
書中的測試框架使用 speclj ↗,與其他主流測試框架類似,讀者很快就能上手。
關於架構與設計#
本書的另一個重點,是描述以函式式風格建構系統時所需的設計與架構原則。為此,作者會:
- 使用統一塑模語言(Unified Modeling Language,UML)圖
- 引用 SOLID 設計原則
- 引用《設計模式》(Design Patterns)的經典模式
- 援引《Clean Architecture》中的概念
需要查閱的外部資料都會在文中標示,讀者不必擔心。
關於物件導向#
許多人認為物件導向(object-oriented programming)與函式式編程互不相容;本書要證明的恰恰相反。
書中的程式、設計與架構會是兩種風格的混合體。作者強烈主張:兩種風格完全相容,優秀的程式設計師可以、也應該同時運用它們。
關於「函式式」一詞#
書中的 functional(函式式)有時會被作者「寬鬆使用」。例如:
- 雖以函式式語言、用函式式風格撰寫,但並非「純函式式」(pure functional)的範例
- 在這類情況,作者通常會以引號標註並用註腳說明
之所以放鬆嚴格定義,是因為這是一本講實用主義而非理論的書。作者更在意如何萃取函式式風格帶來的好處,而不是死守理想模型。例如第 1 章會看到:接受使用者輸入的「函式」其實不是純函式——但這類「函式」仍會被適切使用。
範例程式碼#
書中所有章節的範例程式碼集中放在一個 GitHub 倉庫:https://github.com/unclebob/FunctionalDesign ↗