iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
Software Development

從零開始Reactive Programming- Spring系列 第 4

[Day 3] Reactive Programming - Functional Programming

前言

並不是說Reactive 一定要搭配Functional,只是搭配起來更好用,而後面介紹到的Reactor & WebFlux,基本上也都是Functional Programming,所以在這邊先介紹一下到底何謂Functional Programming。
https://ithelp.ithome.com.tw/upload/images/20210917/201414186PxQwB5fLm.png

圖片來源 tail recursion

Functional Programming?

函式語言程式設計(英語:functional programming)或稱函式程式設計、泛函編程,是一種編程範式,它將電腦運算視為函式運算,並且避免使用程式狀態以及易變物件。其中,λ演算為該語言最重要的基礎。而且,λ演算的函式可以接受函式作為輸入參數和輸出返回值。

上述源自於wiki,簡單的說Functional Programming就是前一天介紹的Programming paradigm其中宣告式的一種,所以她其實就是一種抽象的概念,盡量透過函式來編寫程式碼,會有以下幾個特性。

First-class citizen

值可以指定給變數,也可以當作參數傳入方法(函數)中,則稱為一級值(first-class value)。Java當中int、long、String或是物件等等都可以指定給變數並傳入方法(函數),這些也就是first-class value,而能夠指定給變數以及當作參數的函式,則被稱為First-class citizen(一等公民), Java 8 之後,提供了FunctionsSuppliersConsumersPredicates等等Functional Interfaces,Java 才終於有了First-class citizen。

higher-order function

java 有了First-class citizen之後,隨之而來就是higher-order function,當一個函式(function)傳入一個或多個函式做為參數,他就是higher-order function,舉例來說,在操作Stream的時候常用到的map()filter()flatMap().......等都是higher-order function,他們都是將函式做為參數。

@Override
public Stream<R> filter(Predicate<? super R> predicate) {
 return new StreamDecorator<R>( delegate.filter( predicate ), closeHandler );
}

@Override
public <R1> Stream<R1> map(Function<? super R, ? extends R1> mapper) {
 return new StreamDecorator<>( delegate.map( mapper ), closeHandler );
}

@Override
public IntStream mapToInt(ToIntFunction<? super R> mapper) {
 return new IntStreamDecorator(
   delegate.mapToInt( mapper ),
   closeHandler
 );
}

pure function

同樣的input,一定會輸出相同的output。

no(盡量不要有) side effects

大部分的說明都是沒有副作用,避免狀態或是資料改變,但現實中的企業應用專案,需要去log或是存入db資料,很難去做到完全的no side effects,所以追求最少的副作用是一個折衷的辦法。

immutable

不可更改,也就是當物件的狀態在創建後就不可以更動。

若遵守以上幾個條件,當需要多處理併發(Concurrency)與多執行緒(Parallelism)的時候,程式相對就可以單純許多,畢竟不會改變也就不用去synchronized,而在維運的時候也不會到處去找BUG是否是因為某個狀態不如預期,可想而知這就是Functional Programming的優點之一。下面是一個簡單的將偶數乘上5並加總的範例。

List<Integer> data = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = data
    .stream()
    .filter(i -> i % 2 == 0)
    .map(i -> i * 5)
    .reduce(0, Integer::sum);
System.out.println(sum);
//150

結語

Java 本來的語言特性是更友善物件導向設計(OOP), OOP的特色就是萬般皆物件,用物件的概念去對應並設計程式,比較好入門而且更具體一點不像是Functional 這麼抽象,另外OOP的重點在於資料(DATA),FP則關注於操作(operations),所以有人說若是資料多操作少建議使用OOP,資料少操作多則推薦使用FP。我個人的觀點認為在JAVA中很難完全捨棄掉OOP,所以在OOP中去使用一些FP的寫法或許是一個不錯的辦法。

對oop vs fp有興趣可參考這篇

資料來源


上一篇
[Day 2] Reactive Programming - Programming paradigm
下一篇
[Day 4] Reactive Programming - 觀察者模式Observer Pattern
系列文
從零開始Reactive Programming- Spring32

尚未有邦友留言

立即登入留言