上帝的玩偶:haXe语言
在动画片《我叫MT》中,有个“五火球神教”,五火球神教的口号是“征服世界”。在小说《风姿物语》中疯狂的白家的某代家主白拉登,他手中的扇子上写着“世界征服”四个大字。
疯狂!只能用疯狂来形容。少年们,下面请看一群疯狂的黑客为我们提供的程序语言“征服世界”的解决方案吧!
这里的黑客指的是真正的黑客,是程序世界里勇于尝试和探险的人,不是那些Cracker们。
这是一个激动人心的旅程,其起点来自某个不为人知的角落。
在2005年之前,小小的Flash开源社区中流传着MTASC的传说,MTASC的全称为 Motion-Twin ActionScript 2 Compiler,顾名思义,它是一个ActionScript 2语言的编译器(当时的Flash官方脚本语言),MTASC是用OCaml语言编写的,OCaml语言是一种主流的函数式编程语言,正如《计算机程序的构造和解释》一书使用Scheme所描述,《Types and Programming Languages》和《Advanced Topics in Types and Programming Languages》这两本类型系统的圣经用的是OCaml描述。OCaml是玩类型系统的黑客们的御用语言。
.Net社区所熟知的F#也是基于OCaml的,通俗点讲,F#是OCaml的亲儿子,OCaml是F#的粑粑。
玩函数式语言的家伙们通常身上都有黑客气质,因此,当ActionScript 2 改头换面为ActionScript 3后,开发MTASC的家伙们做出了一个大胆的决定:
“少年不哭,
站起来撸;
不做备胎,
征服世界!”
于是,一门跨平台跨语言的神上神语言横空出世——haXe!而随着移动时代和html5时代的到来,haXe的解决方案竟然是这样的优美和令人赞叹。
与我们知道的语言不同,haXe是一门“Universal Language”,我觉得翻译成“上帝语言”比较准确。haXe是一门超越语言的语言,使用haXe写的程序,可以编译成不同的其它语言源码,再进行编译。如,haXe -> C++,haXe -> JS ,haXe -> as3/swf,haXe -> php。同时,haXe社区又为不同的平台提供了统一的API抽象,形成了跨平台跨语言的解决方案。
haXe开发环境的安装见《拥抱haXe之javascript 也玩mvc》一文,本文详细谈谈我对haXe的理解。
很多程序员言不离OO,好像OO便是很高级的玩意。而在高耸如云的云端,住着一些仙人,口中没有OO,只有类型。我看不懂《Types and Programming Languages》,所以,下面对类型系统的说法只是我的胡乱所想,有可能谬误百出。
在.Net文档中,我们经常看到一个词:Type,对,这就是类型。而对象,则是Object。类型这个词,是高于对象的。C中的int是一种类型,函数是一种类型,C#中的Object是一种类型,每一个编程语言都提供了一种类型系统。类型的水,比OO的水深的多。而haXe,就是一套类型翻译系统,将由haXe类型系统所描述的代码,翻译成目标语言的类型系统,它玩的是类型。
为了跨语言,haXe只提供了简单的基本类型,如Int,Float,Bool,Void等,在基本类型之外,haXe几乎提供了一门现代语言的所有工具:静态类型、动态类型、命名空间、泛型、函数对象、迭代器、内联、继承、多态、getter,setter,接口,mixin,typedef,标准库……。它使用某种高玩们才能理解的技术确保这个类型系统到目标类型系统间正确的转换(不必担心它会发生错误,它的正确性应该是得到证明过的,是证明不是证实啊亲),如此一来,使用haXe就具有两个好处:
(1)使用haXe写的代码,能正确的转换到不同的目标语言,这样,最大程度的达到代码级别的共享。
你可能觉得,这不是带着镣铐跳舞吗?是的,在以前是,但是,现在不是了,现在的平台越来越多元化了。用js写前台的,用js写后台的,用php写后台的,用C#写应用的,用C#写后台的,用C++写应用的,用C++写后台的,用Java写应用的,用Java写后台的……如果一个功能,用一门语言写好了之后,它可以翻译成各种不同的语言,还是很有价值的。虽然C很万能,但也没办法在前台JS中用啊,因此,haXe的这种解决方案是一种很有特色很有针对性的解决方案。比如,我有一个东西,既想通过html5发布,又想通过Flash发布,还想发布成iOS本地应用,那么,有比haXe更好的解决方案吗?没有。用haXe就很简单了,写一份代码,编译成js的,在html5中用,编译成flash的在Flash中用,编译成C++的在iOS中用。再比如,张三的公司要推出一款Web产品,既有PHP版又有.Net版(比如,Discuz这种),用haXe开发可以只维护一份代码。
你可能还有另一个疑问:不同平台间的差异十分大,就算我可以不用Byte,但那些底层API都不一样啊。没关系,haXe社区提供了NME,对不同平台的基本API提供了抽象,还是一份代码,到处编译。实在不行了,你还可以通过条件编译和Magic代码来直接调用外部API。
(2)对于某些弱类型系统,比如js,使用haXe可以带来生产力的极大提高!强大的类型系统啊,亲!大部分错误编译器都帮你检查出来了,亲!有命名空间啊,亲!有泛型啊亲!接口啊,继承啊,多态啊,getter,setter,static等都有啊亲!注释啊,还有那些你用不上的类都不会被编译进js中的啊,亲!还有个小型的标准库啊,亲!
下面谈谈使用haXe的三个主要的场景。
(1)Web APP
随着Html5时代的到来,Web APP会越来越多。以往的Web主要是基于文档的页面,也就是说,一页Web页面,大部分是html和css,JS只是脚本,代码量并不多。而Web APP改变了这一状况,Web APP中,可能html和css代码量会比较少,JS代码会比较多。
以我现在手中的Web APP为例,截至目前为止,只有150行html代码,50行css代码,而JS代码有5000行。JS代码中,大部分是处理业务逻辑,只有一小部分是处理dom。如果使用JS开发,要规划好类,要做好类与类的继承关系还并不是一件简单的事情,又由于不是强类型,代码一多,很难维护。
而我一开始就选用了haXe,就没有这些问题了。把每一个Dom节点当作一个控件,style当作控件的显示属性(haXe中,css直接被typedef为HtmlDom的style对象的属性了),然后,监听各种事件,更新控件的属性即可,就像写Winform程序一样。由于haXe有强大的类型系统,规划好类,一切很顺利的搞定,用的很爽,像写C#程序一样。
看看下面的代码组织,你能想到这是一个js web 应用吗:
好处一:使用命名空间、类来组织代码,代码结构清晰,容易维护。最终,haXe编译器会将使用到的类编译成一个独立的js文件,剔除了用不上的类。发布也很简单;
好处二:由于是强类型,即使我用的是开源IDE,自动完成系统也很完善,打个点就知道类型有哪些成员和操作了;
好处三:使用熟悉的OO开发方式来开发,不用去折腾js那一套类型系统来模拟OO、命名空间等机制;通过mixin,甚至连.Net的扩展方法也可以实现;
好处四:haXe编译器保证了类型的正确处理,将很多js运行期可能出现的错误在编译时就发现了,直接定位到代码的行处,提前解决问题。
这个项目在进行第三期了,预期最终js代码量会达到10000行,如果我直接使用js开发,恐怕是个灾难。
我一直宣称JS是Html5的最大软肋,就在于Web APP一旦复杂起来,JS的缺陷就会开始暴露。你能想象到拥有10000个类的JS代码是什么样子吗(如果要在页面实现Office,CAD,Matlab这样档次的应用,怎么说也得几千个类吧)?而对于这种情况,haXe提供了成熟的解决方案。当然,这个解决方案是误打误撞的,少年不哭,站起来撸,Flash开源社区飞出来一根屌丝,在Html5的土壤中发了芽。
(2)移动APP
在移动开发领域,现在是苹果,Android在主导,还有个老去的黑莓,还有未长大的WP,如何只用一份代码,就开发出上述平台通用的应用呢?haXe同样提供了解决方案,就是haXe+nme,详见网站 http://www.haxenme.org/
WP就不谈了,市场占有率太低,nme还没考虑它。
你可以将NME看作对平台UI和基本OS操作、基本Web操作的抽象,来看看NME的介绍:
“NME targets iOS, Android, webOS, BlackBerry, Windows, Mac, Linux and Flash Player using your same code.”
它的野心不止是移动平台,而是所有的主流平台!
是的,我们要征服世界,尽管我们只是几个孤独的黑客!
这里只提移动APP是因为它的价值主要体现在移动平台上,因为在桌面平台上,有更NB的解决方案,比如.Net,haxe+nme没什么竞争力。
它可以编译成Native APP(这利用的是haXe->C++特性)在桌面或移动平台运行:
“Harness native features and performance without writing C++ or Objective-C.”
这一点挺有竞争力的。目前虽然Flash也能做到在部分平台编译为Natice APP,但是ActionScript3的性能比不上C++。同时,Flash的移动应用的尺寸比较大,也是一个缺陷。
它也可以编译成Flash程序在浏览器或者移动平台运行:
“Compile for Adobe AIR or Adobe Flash Player using the same codebase.”
这一点唯一的实用价值是编译成Flash程序,可以Web上浏览。编译为Flash 移动应用还不如直接编译成C++移动应用,尺寸更小,速度更快。
它也可以编译成Html5应用在浏览器上运行:
“Designed to work with Jeash for rich HTML5 applications in your web browser.”
Jeash是一款html5平台实现的Flash API,而NME实现的也是Flash的API,所以这一来,就有点意义了。
这里有haxe+nme的案例,全部是游戏:
http://www.haxenme.org/showcase/
这是一个巧妙的跨平台解决方案。当然,这个解决方案依然是误打误撞的,无论是haXe还是nme,都比iphone年龄大。少年不哭,站起来撸,Flash开源社区飞出来一根屌丝,在移动应用的土壤中发了芽。
(3)Flash APP
haXe的前身MTASC的唯一用途就是开发Flash应用,而进入haXe时代后,Flash APP反而是最不值得关注的一个领域了。haXe开发相比as3开发优势不多,一个优势是haXe提供了一些Flash未公开的API操作,可以提高性能;另一个优势就是haXe编译速度非常快。这两个优势都不是决定性优势,我觉得没多大发展前途,haXe的主要前途应该是html5领域和移动应用领域。
而未来,不是Web APP压倒移动APP,就是移动APP压倒Web APP,无论哪一个取胜,都没有关系的。有了haXe,你就是上帝。
对性能特别敏感的应用,haXe还搞不定,或者,你得hack一下haXe。haXe的核心代码就那么几个文件,几千行。
最后,来一首安蕾尔的《Evil Evil》: