
【Guava 教學】(10)進行函數式程式設計
【Guava 教學】(9)ListenableFuture 聽取未來需求 << 前情 由於 JDK8 Lambda 的引進,未來 JDK8 將有進行函數式程式設計的可能性,剛好本站 Java 開發者的函數式程式設計系列 已經告一段落,閱讀該系列的文章,將有助於將來在 JDK8 中,善用那些從函數式程式設計借鏡而來的相關設計,無論是 Lambda 語法或程式庫的使用。 那麼在 JDK7 前的版本呢?如果想在 Java 中進行函數式風格的設計有可能嗎?其實有一些第三方程式庫提供了這類風格的封裝,其中包括了 Guava 程式庫,然而缺少 Lambda 語法的輔助,使用 Guava 程式庫的相關 API 並不一定會因為函數式風格而受益,正如 Guava 的 FunctionalExplained 中提到的,除非使用這些 API 進行函數式風格設計時,對可讀性有所幫助,或者是取得了 惰性 處理上的一些益處,不然命令式仍應是 Java 的風格選擇。 雖然 Guava 的 FunctionalExplained 中也提到,其函數式風格的 API 主要是針對 JDK5 到 JDK7 的使用者,不過使用 JDK8 的 Lambda 語法來搭配 Guava 的函數式風格 API,似乎也是不錯的選擇,特別是你要與 Guava 的其他 API 做溝通,或甚至你覺得 JDK8 的 API 設計得有些醜陋時。 Guava 的 Iterable<String> filteredNames = filter(names, name -> name.length() < 5); 看到傳回值是 Iterable lengthes = transform(names, name -> name.length()); Guava 不提供
Iterable<String> filteredNames = filter( names, and(name -> name.length() < 5, name -> name.startsWith("Java")) ); 那麼,如果想進行鏈狀操作呢?畢竟上面的寫法,比較像是 Java 開發者的函數式程式設計(5) 提到的, boolean anyJAVA = any(transform(filter(names, name -> name.length() < 5), name -> name.toUpperCase()), name -> name.equals("JAVA")); 幾乎沒什麼可讀性,你可以改用 boolean anyJAVA = FluentIterable.from(names) .filter(name -> name.length() < 5) .transform(name -> name.toUpperCase()) .anyMatch(name -> name.equals("JAVA")); 曾經聽其他人說過,看不懂 加上這篇文章,相信再去看 Guava 的 FunctionalExplained,就可以知道它上頭在說些什麼了。
|
Valentino Young
02/20
Guava的FunctionalExplained, 跟函數式設計其實是同曲異工.
標題之所以用 explained 而非 programming,
表示代表著 "用函數風格詮釋代碼意圖" 而非全然的 "函數式程式設計".
表示看不懂Iterables上那些方法怎麼使用的, 並非缺乏對函數式設計的瞭解或便捷的語法之所致,
就跟過去覺得用if/for/swithc/while巢狀迴圈才是簡單的直覺的容易看懂的,
不瞭解以CollectionUtils(Iterables懷舊版)為重心的設計的好處在哪裡...的原因相近,
就是其"程式設計師"的頭銜不符"設計師"之實的老問題而已.
若以函數式設計為出發點,
注意力會集中在apache的CollectionUtils, Guava的Iterables, JDK8的Stream等等的主引擎,
然而以一個又一個的系統建置用來服務數十數百個縱向業務邏輯,
然後橫斷式需求的變更又不斷與時俱進, 或朝秦暮楚...的經歷而言,
AndPredicate/AllPredicate(Guava:AndPredicate)
,ChainedTransformer(Guava:FunctionComposition)
,PredicateTransfomer(Guava:PredicateFunction)
,TransfomedPredicate(Guava:CompositionPredicate)
,NOPClosure,TransformerClosure,ExceptionClosure...
...諸如此類被引擎運轉帶動的輔助器械的活用才是重點.
雖然已經有些年歲, 不過org.apache.commons.collections.functors仍舊值得一看,
除了翻遍主引擎的JavaDoc跟原始碼意圖將其運用至極限之外,
多用輔助器械而讓主引擎簡單運轉即可一樣能達到相同目的...的角度, 也是值得考慮的.
Guava在cleancoder的表現當然是比2002年就出現的apache collection成熟許多,
唯獨個人覺得把Transformer變成Function並不是那麼地適當, 那是函數式程式設計風潮使然...
以FunctionalExplained為題而非functional programming,
CollectionUtils的transform方法到了Iterables上仍舊名為transform,
...暗示著與函數式程式設計雖然調性相符但本質仍舊是不同的實情.