劉德財 高建華
(上海師范大學計算機科學與技術系 上海 200234)
?
基于函數式編程語言的事件驅動模型的設計與實現
劉德財高建華
(上海師范大學計算機科學與技術系上海 200234)
函數式編程語言在移動游戲研發中使用十分普遍,例如客戶端的Lua、JavaScript,服務端的Ruby、Erlang、JavaScript。但目前對移動游戲開發框架的設計大多是基于傳統面向對象的方法,并沒有很好地利用函數式編程語言的特性。針對項目代碼模塊的通信問題,通過借鑒面向對象(OOP)中的觀察者模式以及現有的函數式編程語言的開源框架Node.js,設計并實現一種適用于函數式編程語言的事件驅動模型FPEDM(Functional Programming Event Driven Model)。該模型具有簡單易用,擴展性強,與移動游戲軟件耦合度低、復用性好的特點,應用到項目開發中可大大提高開發效率,簡化項目框架的復雜度。
函數式編程事件驅動模型
隨著移動智能設備的配置不斷提高以及移動互聯網技術的快速發展,移動游戲的開發設計變得越來越重要。移動游戲的開發和傳統的端游開發有著很大的區別,端游一般開發周期長,項目龐大復雜,引擎技術由于不開源而更新周期較長,開發語言一般為面向對象語言,如C++、Java等,而移動游戲則開發周期短,游戲版本迭代快,引擎技術開源使得引擎技術更新較快,開發語言趨向于函數式編程的動態語言,如Lua,JavaScript,Ruby等。目前在移動游戲開發框架設計領域的研究比較少,實際開發中很多也還是照搬了傳統面向對象(OOP)的設計思想,沒有很好地利用函數式編程語言的特性,使游戲項目變得龐大復雜,并不能很好地適應開發周期短、項目變更快的移動開發,同時編程語言本身的差異也使得在實現OOP設計思想上有困難。
本文就移動游戲開發框架設計中的代碼模塊間通信問題進行設計和研究,通過借鑒面向對象(OOP)的觀察者模式和開源框架Node.js[1],設計并實現了基于函數式編程語言的一種事件驅動的模型框架FPEDM,該模型具有易使用,易擴展,可復用的特點,同時模型也充分利用了FP語言的特點,更加適合FP語言編寫的移動游戲項目,更為重要的是把設計思想提取成為了一個文件,不依賴任何具體的移動游戲項目。FPEDM應用在實際開發中可大大提升項目開發效率和軟件質量。
1.1函數式編程
函數式編程和指令式編程(面向過程編程和面向對象編程)相比較,函數式編程提升了函數的地位,函數是第一類對象和數據的集合,使得編程者對程序的狀態和執行次序不必太關心[2]。
1.2函數式編程語言
函數式編程語言的構成范式的理論基礎是由Alonzo Church等提出并證明與圖靈機等價的lambda演算系統,在該范式下,程序由函數和對函數的應用上下文構成[3]。相對于Objective-C,蘋果最新發布的開發語言Swift一個很重要的改進就是就加入了函數式編程的支持。
1.3事件驅動模型
事件驅動模型在軟件設計中主要涵蓋三個方面:事件源、事件和事件處理者[4]。事件(如GUI中的敲入一個鍵、單擊鼠標)發生后,事件源就會激發與此事件相應的消息,事件調度器將事件傳給事件處理者的處理函數進行處理。
2.1FPEDM的設計
傳統的軟件工程中,事件驅動模型的設計一般如圖1所示。首先由事件注冊者在事件調度器中注冊/移除注冊特定的事件,事件處理者同時向調度器監聽/取消監聽特定的事件,事件源發生事件后告知事件調度器發生了某個事件,事件調度器收到后通過派發告知正在監聽這個事件的每一個處理者,讓所有處理者對事件作出響應[5]。
傳統的事件驅動模型設計充分體現了面向對象的設計思想,優點是可擴展性好,缺點是設計較為復雜。一個事件的完成需要多個參與者,如圖1所示一般需要四個參與者,這也導致開發人員在理解和使用上成本較高,這在開發周期長的大型項目中是能夠承受的。但在開發周期較短、迭代迅速的移動游戲項目中,顯得有些設計過度,不利于移動游戲項目的快速開發和BUG排查。

圖1 面向對象的事件驅動模型
本文通過借鑒面向對象中的觀察者設計模式[6]和開源框架Node.js[7],設計了如圖2所示的基于函數式編程語言的事件驅動模型(FPEDM)。FPEDM中一個事件的參與者只剩下事件源和事件處理者,其中事件源通過引用FPEDM文件,具有了注冊/取消注冊事件和事件派發的功能,事件處理者通過向事件源(同時也是事件調度器)監聽/取消監聽特定的事件。FPEDM中的事件源在事件發生時派發事件,所有正在監聽這一事件的事件處理者都會收到,從而作出響應。FPEDM使得整個事件驅動的模型變得簡單易用,模型不依賴于具體的移動游戲項目,做到了思想和代碼的100%復用,并且實現了和圖1一樣的功能。

圖2 FPEDM
2.2FPEDM的實現
從圖2中可以看到, FPEDM的關鍵就是FPEDM文件的實現。從2.1節可以知道,事件驅動模型包含6個過程:注冊/取消注冊,監聽/取消監聽,發生和派發,其中發生是事件源的職責,事件源應該明確知道事件何時發生。因此FPEDM文件只需實現注冊/取消注冊,監聽/取消監聽、派發5個過程以及引用FPEDM文件的方法即可。
本文中描述FPEDM文件的實現采用的是moonscript風格的偽代碼,moonscript是lua的模板編程語言。
FPEDM文件對于注冊/取消注冊采用了一張哈希表(Hash table)進行維護,具體結構如圖3所示,該數據結構充分利用了函數式編程語言的函數是第一類對象的特點。哈希表中的關鍵碼值為事件ID,關鍵碼值所對應的是所有正在監聽這一事件的處理函數的指引(函數式編程語言中沒有指針概念,本文稱為指引)的集合。

圖3 FPEDM的數據結構
FPEDM文件的添加監聽方法如圖4所示,其中輸入為事件源,事件ID以及監聽者(處理函數),函數中第一個參數self為函數的調用者。從圖2可以知道FPEDM文件是被事件源引用的,所以這個self就是事件源,第3行的findOrCreateListenerTable函數是創建或者找到已存在的圖3所示的數據結構,即得到event_id的所有處理函數的指引集合,第4行為向這個集合中添加監聽者listener,最后返回self(事件源)是為了方法的鏈式調用。

圖4FPEDM文件的addListener方法
FPEDM文件的移除監聽方法如圖5所示,其中輸入為事件源,事件ID以及監聽者(處理函數),第4、5行得到event_id的處理函數集合,并從中移除listener,第6、7行為移除一次性的監聽者。一次性監聽者的添加和圖4方法基本一致,只是在event_id后添加once字符組成新event_id以區別正常監聽者,它會在收到事件作出響應后自動移除監聽。

圖5FPEDM文件的removeListener方法
FPEDM文件派發事件的方法如圖6所示,輸入為事件源,事件ID,以及事件派發時所帶的參數(可以多個參數),第2-5行得到event_id的處理函數集合,并依次調用。每次調用時都會把派發所帶的參數傳給處理函數,這樣使得事件源和監聽者之間可以進行數據交流,第6-10行為處理一次性監聽者的響應,并在10行自動移除監聽。

圖6FPEDM文件的emit方法
引用FPEDM文件的EventEmitter方法如圖7所示,從圖2可知輸入為事件源,第2行對引用對象(事件源)設置標志位,標記其擁有了FPEDM文件的方法,3-9行依次把FPEDM文件中的方法賦予引用對象(事件源),并借鑒了Node.js的API風格為每個方法取了別名,便于理解和實際應用。

圖7FPEDM文件的EventEmitter方法
3.1簡單易用
項目使用FPEDM十分簡易,它和Web的js文件使用方法類似,只需要在事件源文件中引用FPEDM文件,調用EventEmitter注冊自身后即可。圖8展示了FPEDM的使用。

圖8FPEDM的使用示例
3.2充分利用了函數式編程語言的特點
FPEDM充分利用了FP語言編程的文件模塊化和函數為第一類對象的特點,無需再把FP語言偽裝成OOP語言來使用,靈活度提高了不少,代碼之間的邏輯關系變得更加清晰,沒有復雜的繼承和龐大的UML類圖。
3.3分布式的事件管理機制
傳統事件調度器一般都存在輪詢代碼,不斷輪詢每一個事件的狀態,從而做出是否派發事件的決定。FPEDM中的事件源通過引用FPEDM文件后,可以實現自己管理自己的事件,無需單獨的事件調度器存在。由于這種分布式的事件管理機制,在一定程度上可以消除移動游戲項目中的代碼中心瓶頸問題。
3.4實現了模型和代碼的100%復用
由于FPEDM的代碼獨立成了一個模塊文件,使得只要是和FPEDM文件使用同一門語言編寫的移動游戲項目,無需任何的修改即可直接使用,而且使用過程十分簡單方便。同時理論上任何FP語言都可以實現FPEDM文件,所以對使用FP語言編寫的項目來說,使用FPEDM都是一個不錯的選擇。
3.5保留了OOP式事件驅動模型的優勢
表1列出了FPEDM和傳統面向對象(OOP)的事件驅動模型對比結果,因為兩個模型都是對軟件的一種設計,所以對比的指標采用了軟件工程中常用的評價指標,包括了復用性,易用性,可維護性和擴展性[8]。從表1的結果可以看出FPEDM保留了OOP式事件驅動模型的可維護性和擴展性特點,提升了事件驅動模型的代碼復用性,降低了事件驅動模型的使用和理解門檻,在移動游戲開發中的實際效果也證實了這些優勢。

表1 OOP式事件驅動模型和FPEDM對比
本文通過借鑒傳統軟件設計思想中的觀察者模式和開源框架Node.js,設計并實現了基于函數式編程語言的FPEDM,并把其和傳統OOP式事件驅動模型相比較,得出FPEDM具有簡單易用、充分利用了FP語言特性、分布式事件管理機制、代碼復用率100%和保留了OOP式事件驅動模型優勢的特點,使其十分適合用于移動游戲項目(FP語言開發)的開發和設計。日后的研究主要是實現FPEDM中多事件協作的處理和事件的異步驅動等。
[1] Node.js的模塊機制.https://Node.js.org/api/modules.html.
[2] 微軟關于函數式編程的定義和解釋.https://msdn.microsoft.com/en-us/library/bb669144.aspx.
[3] 李向陽,連小綺.函數式程序范式在語義web中的應用[J].中國科技信息,2006,12(24):79,87.
[4] 韓彪,吳眾欣,欒鐘治,等.一種適于主-從模式網絡計算的事件驅動架構[J].西安交通大學學報,2010,44(2):39-43.
[5] Westermann U,Jain R. Toward a Common Event Model for Multimedia Applications[J]. MultiMedia, IEEE, 2007,14(1):19-29.
[6] Zhu G K. Applying Software Design Patterns in Electromagnetic Field Simulators[J]. Antennas and Propagation Magazine, IEEE, 2012,54(2):174-179.
[7] 王金龍,宋斌,丁銳. Node.js:一種新的Web應用構建技術[J].現代電子技術,2015,38(6):70-73.
[8] Ian Sommerville. 軟件工程[M]. 程成,陳霞,等譯.北京:機械工業出版社,2013: 178-192.
DESIGN AND IMPLEMENTATION OF EVENT-DRIVEN MODEL BASED ON FUNCTIONAL PROGRAMMING LANGUAGE
Liu DecaiGao Jianhua
(Department of Computer Science and Technology, Shanghai Normal University, Shanghai 200234,China)
Functional programming language (FPL) has been widely used in the development of mobile games, such as Lua and JavaScript on client, Ruby, Erlang and JavaScript on server. However, most of the designs in regard to mobile game development framework are based on traditional object-oriented method, they do not make good use of the characteristics of FPL. In this paper, focuses on the communication in modules of project code, we designed and implemented an event-driven model applicable to FPL, named FPEDM, by referring the observer pattern of object-oriented programming (OOP) and existing open source framework of FPL Node.js. The model is simple and easy to use, has strong scalability, low coupling dependency with specific mobile game projects, and good reusability. By applying it to project development, the development efficiency can be greatly improved, the complexity of the project framework can be simplified as well.
Functional programmingEvent-driven model
2015-06-06。國家自然科學基金項目(61073163);上海市企業自主創新專項資金項目(滬CXY-2013-88)。劉德財,碩士生,主研領域:軟件可靠性設計理論與方法。高建華,教授。
TP3
A
10.3969/j.issn.1000-386x.2016.09.002