《無瑕的程式碼 函數式設計篇》推薦序

《無瑕的程式碼 函數式設計篇》推薦序

無瑕的程式碼 函數式設計篇

這本《無瑕的程式碼 函數式設計篇》並不是在討論「函數式程式設計」。它是談論更高層次的原則、模式與實踐。書中進行了大量的物件導向程式設計(Object-Oriented Programming,OOP)與函數式程式設計(Functional Programming,FP)的討論。OOP採用Java展示,FP則採用Clojure展示。

我不可否認,在閱讀的過程中,Clojure程式語言會是一個門檻。我認為造成這個門檻的部份原因是因為Clojure程式語言的中文資源相對稀少。除了書中提供的一些速成資料外,想要多了解Clojure程式語言需要讀者多花費些功夫。但這不影響討論精華,回到書中,讓我來快速整理一下OOP與FP之間的特點:

物件導向程式設計的特點

  • 狀態與行為的封裝:物件導向透過類別將狀態與行為封裝在模組內部,強調物件之間的互動。提供直觀的結構,方便理解和設計大型軟體系統。
  • 抽象與繼承:抽象化的層次設計允許通過基礎類別和子類別關係來組織程式碼,便於重覆使用。
  • SOLID設計原則:SOLID原則在物件導向中尤為重要,例如單一職責、開放封閉等,以促進系統的可擴展性與維護性。

這其中的精華淬鍊出來就是我們熟知的設計模式(Design Patterns)。

函數式程式設計的特點

  • 參考透明性與純函數:函數式程式設計避免副作用,函數僅根據輸入返回輸出,確保程式的穩定性與可測試性。
  • 不可變性:透過不可變的資料結構減少狀態改變所帶來的錯誤,尤其適用於多執行緒環境。
  • 遞迴代替迭代:使用遞迴來移除變數的指派,並通過尾端呼叫最佳化(TCO)提升效能。

這其中我認為遞迴(recursion)與迭代(iteration)的觀念尤為重要,不論是在OOP或FP的世界都是非常重要的核心觀念。

遞迴核心觀念

  • 去變數化:函數式程式設計避免使用可變變數,而遞迴通過傳遞參數實現狀態的演進。每次遞迴呼叫都是以新的引數值代替舊的狀態,讓程式邏輯更加清晰。
  • 尾端呼叫最佳化 (Tail Call Optimization, TCO):書中提到遞迴是函數式程式的基石,但需要透過TCO避免堆疊空間的浪費。尾端呼叫將最後一次遞迴最佳化成跳回函數的開頭,重用堆疊框架,提升效能。
  • 結構的優勢:遞迴更接近數學歸納的思維方式,程式碼簡潔且直觀。使用遞迴能更自然地處理樹狀結構或分治問題(divide-and-conquer)。

迭代的應用與限制

  • 迭代的效率:傳統的迭代(如for和while循環)在程式設計中具備明顯的執行效率優勢。它對記憶體的占用更少,不需要堆疊的管理。
  • 缺乏不可變性:迭代通常依賴於可變變數,因此需要額外處理狀態變更的副作用。

遞迴適合問題的分解和層次化,尤其在需要解決如樹形或圖形結構的問題時。迭代偏向直接和程序式(procedure),適合線性結構處理。這是讀者可以多加琢磨的地方。

書中不斷證明,OOP能行之事,FP一樣能行;但OOP與FP兩者之間並非互斥,而且互補的關係,兩者可以在設計中共同使用。函數式程式設計可用於增強物件導向的穩定性與彈性。書中也展示如何在物件導向中運用函數式的技術,減少耦合,提升系統設計的靈活性。

讀者在學習這些原則、模式與實踐會面臨不小的挑戰,例如,過度依賴單一範式,書中提醒,無論物件導向或函數式,都有其不足之處,避免陷入某一範式的偏見。如何在工作中權衡,根據具體需求選擇適當的方式,如在多執行緒中偏向函數式的不可變性,而在大型結構化系統中更依賴物件導向等等,學習的關鍵,在於擺脫範式迷思,靈活選擇最適合當下情境的設計方法。

此書讀起來,讀者會較有壓力的地方(我也是),除Clojure程式語言之外會是在範例的參考資料。書中的範例多數來自Uncle Bob的其他圖書,例如《無瑕的程式碼 軟體工匠篇》(Clean Craftsmanship)剛好是我審校,因此我知道這些範例的精彩之處,但書中非常專注在討論函數式主題,對於這些借來的題目,並無過多的說明。當然,或許Uncle Bob認為,對於一本新出版的圖書來說,他前面的系列圖書,讀者們應該都已經讀過了。(應該書架上都有一排Uncle Bob系列,能隨時回去翻閱!)

總而言之,《無瑕的程式碼 函數式設計篇》不是單純的函數式程式設計教科書,而是一場從原則到實踐的深度對話。對於渴望持續進步的程式設計師,它帶來的不僅是技術知識,還有一種重新審視與平衡開發思維的啟示。

天瓏購買:無瑕的程式碼 函數式設計篇:原則、模式與實踐

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。