2015年8月31日

Reactive Programming 響應式程式設計方法

Reactive Programming 是以 data flow 以及傳遞資料改變這兩點為核心,提出的一種 programming paradigm,尤其在 GUI Programming 的領域中,簡易的 Reactive Programming Model,讓 Programmer 能用更直覺的方式,取得資料的串流,並能跟著時間的流動,改變整個畫面的呈現結果。

Imperative vs Reactive Programming

在程式中,如果寫下

b:=2;
c:=3;
a:=b+c
// a 為 5

這個 statement,這時候 a 的結果就會等於 b+c 的運算結果,也就是 5。

然而如果在後面 b 或 c 改變了自己的數值

b:=3;
// a 為 5 或 6?

程式並 "沒有" 再寫一次 a:=b+c,如果 a 還是一樣保持不變,還是等於 5,這就是 imerative programming。

但是如果 a 自動跟著 b 的數值改變,自動再次運算了 b+c,a 自動變成了 6,這就是 reactive programming。

Excel, Spreadsheet

Reactive Programming 乍看起來有點奇怪,這跟我們學習過的程式語言 C 或是 Java 根本都不一樣,變數不應該隨著另一個變數自動改變自己。

但其實有用過 Office Excel 或是其他 Spreadsheet 試算表軟體的使用者,就已經是在做 Reactive Programming了。

在下面的例子中,C1 設定為 A1 + B1 這兩個儲存格的總和,當 A1 的數值改變時,C1 也會自動改變結果。

Office Excel 是辦公室的試算軟體,換句話說,Reactive Programming 其實是比較人性化的程式設計方法,而 Imperative Programming 是為了避免程式設計師撰寫程式時出錯,而刻意將自己簡化的結果。

畢竟當我們撰寫程式時,寫下這樣的 statements 的時候,沒有一個人會直覺地認為 a 的結果會是 6,因為大腦線性運算的結果,只會記得 a 是 5。

b:=2;
c:=3;
a:=b+c
b:=3;

那為什麼又討論起 Reactive Programming 呢?這跟最近幾年流行起來的 Functional Programming 有關係。

Functional Reactive Programming

回到剛剛的 Excel 範例,其實 C1 儲存格隱藏著一個意義,就是 C1 := SUM(A1 + B1),C1 永遠會等於後面這個 function 的運算結果。

在不支援 Reactive Programming 中,要實作出 Reactive 的功能,必須要用 Observer Design Pattern,程式中向原始資料,註冊 Observer,當原始資料異動時,就會呼叫 Observer 的 Lisener Function,主動進行對應的資料異動處理。

也許有人會想,Functional Programming 的基本原則,變數應該都是 immutable value,為什麼會有 Functional Reactive Programming 呢?

Functional Programming 將 Function 視為 first class citizens,而 Function Reactive Programming 並不是單純地將 Reactive 的概念用在變數上,而是將資料視為一個 time-varying values,依照時間變動的數值。

這個互動模式最常見於 GUI 的實作上,FRP 定義了兩種會跟著時間改變的資料:events 與 behaviors。

  • events 代表一個特定時間的數值,例如使用者在鍵盤上敲了一個鍵,就產生了一個 Event Char,並以 (t, 'a') 來表示這個 event。實際上的程式並不直接處理 event,而是處理 event stream,因為時間的連續性,讓鍵盤輸入資料也變成了一個無限的資料串流。

  • behaviors 代表跟著時間持續變動的數值,例如滑鼠游標的位置,因為滑鼠的位置是永遠存在的,而且永遠一直在改變,所以我們可隨著時間的流動,持續取得滑鼠的位置串流。

針對跟著時間流動產生的數值串流寫的程式,其實不需要 Functional Language 也可以撰寫,將 Functional 結合 Reactive Programming 的優勢在於,Functional Language 能夠直接 function 來進行運算,而這個 function 恰好可以表示有著無限資料的 stream,這可簡化大量的程式語法。

ELM Programming Language

網頁是目前最常見的 GUI,以往我們需要了解 html, css, javascript,還要知道怎麼操作 DOM Tree,讀了一堆東西,才算是知道怎麼撰寫網頁程式。

ELM 程式語言,是針對網頁 UI 設計的一種 Functional Reactive Programming Language,他可以即時編譯成 html 與 javascript,因此可以打包放到網頁上運作。

我們可以直接看一下 Mouse Example,簡單的一個 statement: Mouse.position 就可以持續取得滑鼠的位置。

為什麼要提到 Game 呢?因為網頁的遊戲開發,如果使用 javascript,將會耗費 programmer 相當多的時間,也許可以採用某個 javascript framework簡化開發,而 ELM 是直接用另一種程式語言的方式,取代掉繁瑣的 javascript。

看看這兩個實際的例子,就能實際感受到,簡潔的語法帶來的開發優勢:
Mario
Elmtris

References

也談響應式編程

遊戲編程的未來——FRP(函數式反應型編程)

Reactive Programming wiki

Reactive programming - 響應式編程

關於 Elm 的分享, 底稿

使用函數式編程語言 ELM 開發遊戲

FRP與函數式

The introduction to Reactive Programming you've been missing

Functional Reactive Programming (FRP)

Quora: What is Functional Reactive Programming

An Introduction to Functional Reactive Programming