基于函数式编程语言的事件驱动模型的设计与实现
2016-11-09刘德财高建华
刘德财 高建华
(上海师范大学计算机科学与技术系 上海 200234)
基于函数式编程语言的事件驱动模型的设计与实现
刘德财高建华
(上海师范大学计算机科学与技术系上海 200234)
函数式编程语言在移动游戏研发中使用十分普遍,例如客户端的Lua、JavaScript,服务端的Ruby、Erlang、JavaScript。但目前对移动游戏开发框架的设计大多是基于传统面向对象的方法,并没有很好地利用函数式编程语言的特性。针对项目代码模块的通信问题,通过借鉴面向对象(OOP)中的观察者模式以及现有的函数式编程语言的开源框架Node.js,设计并实现一种适用于函数式编程语言的事件驱动模型FPEDM(Functional Programming Event Driven Model)。该模型具有简单易用,扩展性强,与移动游戏软件耦合度低、复用性好的特点,应用到项目开发中可大大提高开发效率,简化项目框架的复杂度。
函数式编程事件驱动模型
0 引 言
随着移动智能设备的配置不断提高以及移动互联网技术的快速发展,移动游戏的开发设计变得越来越重要。移动游戏的开发和传统的端游开发有着很大的区别,端游一般开发周期长,项目庞大复杂,引擎技术由于不开源而更新周期较长,开发语言一般为面向对象语言,如C++、Java等,而移动游戏则开发周期短,游戏版本迭代快,引擎技术开源使得引擎技术更新较快,开发语言趋向于函数式编程的动态语言,如Lua,JavaScript,Ruby等。目前在移动游戏开发框架设计领域的研究比较少,实际开发中很多也还是照搬了传统面向对象(OOP)的设计思想,没有很好地利用函数式编程语言的特性,使游戏项目变得庞大复杂,并不能很好地适应开发周期短、项目变更快的移动开发,同时编程语言本身的差异也使得在实现OOP设计思想上有困难。
本文就移动游戏开发框架设计中的代码模块间通信问题进行设计和研究,通过借鉴面向对象(OOP)的观察者模式和开源框架Node.js[1],设计并实现了基于函数式编程语言的一种事件驱动的模型框架FPEDM,该模型具有易使用,易扩展,可复用的特点,同时模型也充分利用了FP语言的特点,更加适合FP语言编写的移动游戏项目,更为重要的是把设计思想提取成为了一个文件,不依赖任何具体的移动游戏项目。FPEDM应用在实际开发中可大大提升项目开发效率和软件质量。
1 相关知识
1.1函数式编程
函数式编程和指令式编程(面向过程编程和面向对象编程)相比较,函数式编程提升了函数的地位,函数是第一类对象和数据的集合,使得编程者对程序的状态和执行次序不必太关心[2]。
1.2函数式编程语言
函数式编程语言的构成范式的理论基础是由Alonzo Church等提出并证明与图灵机等价的lambda演算系统,在该范式下,程序由函数和对函数的应用上下文构成[3]。相对于Objective-C,苹果最新发布的开发语言Swift一个很重要的改进就是就加入了函数式编程的支持。
1.3事件驱动模型
事件驱动模型在软件设计中主要涵盖三个方面:事件源、事件和事件处理者[4]。事件(如GUI中的敲入一个键、单击鼠标)发生后,事件源就会激发与此事件相应的消息,事件调度器将事件传给事件处理者的处理函数进行处理。
2 FPEDM的设计和实现
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 FPEDM的评价
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对比
4 结 语
本文通过借鉴传统软件设计思想中的观察者模式和开源框架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