Steve Yegge 把 Rails 移植到 JavaScript/Rhino

  • Geoffrey Wiseman
  • 李剑

2007 年 6 月 30 日

话题:JavaRubyWeb框架Ruby on RailsJavaScriptGoogle语言 & 开发

在上周末的Foo Camp上,来自 Google 的 Steve Yegge 发表了一个名为“Google Rails Clone”的演讲,Johm Lam报导说,Steve Yegge 主要谈的是他在 Google 中把 Ruby on Rails 移植到 Javascript 上来的工作经验:

为了提高 Google 中开发人员的生产力,Steve 一直在力求劝服公司引入 Rails(乃至 Ruby)作为开发语言之一。可惜公司对此置若罔闻(Google 并不想增加他们基础架构上所要支持的语言种类),这时候 Steve 就决定做一件任何其他决心受挫的程序员都会做的事情:他把 Rails 逐字逐行的移植到了 JavaScript 上面。

可以想象的出,这件事情在软件开发社区中引起了极大的反响,而大家也是各抒己见,争论不已。这项努力也让我们联想起其它一些项目,尤其是TrimPath Junction,这是另外一个打算用Javascript 移植 Ruby on Rails 的项目,当然还包括PhobosHelma。很多人认为这证实了Yegge 的“Next Big Language”就是 JavaScript 或者 ECMAScript,并提到了 Steve 最近所发的Marshmallow译者注:很不幸的是这个链接似乎被 GFW 了)和丰盛的编程大餐两篇帖子。有些人开始考虑它与.NET on Rails 的关系,还有些则对 Steve 付出的努力表示质疑。这之后 Steve又写了篇博客来详细解释他的想法和感受

InfoQ 有幸对 Steve Yegge 进行了采访。在采访中,他对相关的问题进行了逐一答复。不过他很快就指出,他的话只代表个人意见,与 Google 无关,并希望大家不要依此来臆测 Google 的整体战略。

很多人最关心的就是他们如何才能参与到这个项目中来,这项成果是否会公开和 / 或开源,以及发布的日期,Steve 表示他们已经讨论过这件事情,将来也会认真考虑,但绝对不会在近期内进行:

我们商量过把我们的“Rhino on Rails”开源的问题,不过到目前为止我们还只是随便闲扯而已。原因之一在于我们只能把开发框架安排在比开发相应实际应用次要的位置,最多不过 20% 的工作时间,所以它的进展一直比较缓慢。另外就是我们同时还要依赖 Google 内部的一些基础架构组件,它们自己还在被开源化的过程中,我也不知道有哪些已经被公布出来了。

但问题的关键在于,我们正在观望基于 JVM 上 Rails 风格的 Web 框架这个领域内的争战。现在已经有了很多处于不同成熟期的 Rails 克隆产品,它们包括:JRuby on Rails,Grails,Phobos,TrimPath 还有半打左右的其它产品。

如果经过几年以后,它们中有一个能够站上舞台成为事实标准,并且符合 Google 内部关于安全、性能、可伸缩性和国际化支持的质量标准,那么我们干嘛还傻乎乎的不移植到那上面去呢。

也许它会做大,也许它用过不久就会被扔到一边,永远不会飞出我们这个小组成为开源项目。不过无论如何,要到几年以后才能看出它会走上哪条道路。任何一款平台都要用很长的时间才能趋于成熟,而 Web 框架这个领域至今还仍是动荡不休。

所以这项成果任何面向公众的版本都要依赖于未来 2~3 年内开源市场的状况,以及 Google 内部的支持——这一点在一年左右还是很难有定论的。

谈到 Rails,以及 Rhino 到底是一个“移植版”或者只是一个由 Rails 引发灵感的框架时,Steve 说:

我从 Rails 一出现的时候就喜欢上了它。我也喜欢 Ruby,即使是完全抛开 Rails 来看的时候。但就开发 Web 页面而言,我从来没有遇到过像 Rails 这样优美的框架。再加上不尽其数的关于我们的女英雄——Rails 的话题,还有默默支持着她的精灵伙伴——Prototype 和 Scriptaculous,更不用说为数众多的从各种语言脱胎而出的 Rails 克隆版本,我不得不说,DHH 在创建 Rails 的时候,确实探索出了一条独一无二并且意义深远的道路。赞!

记者又就 Rhino 是一个“移植版”或是一个由 Rails 引发灵感的 Javascript 框架进行了重点提问,Steve 说:

我已经尽我所能的在 JavaScript 的限制内做到了真正意义上的移植,不过还限于 ActionView 和 ActionController 的部分 [还有 Railities],没有 ActionMailer……嗯,还应该再加上一丁点的 ActiveRecord,虽然我们在很大范围内都被限制在如何和后端通信的问题上。从长远角度看,我觉得后端应该会使用 Hibernate。不过我们已经对它进行了逐步扩展,来让它比 Rails 拥有更好的性能、安全性和国际化支持。所以这个 Delta 版可以说是相当精彩的,一本讲解 Rails 的书也不过最多能让你精通这个框架 60% 的特性而已……我们还为它开发了一些很漂亮的工具支持,包括优秀的调试器和其它一些用于 Eclipse 和 Emacs 上的 IDE 功能。

在说到为什么没有直接使用 Ruby on Rails 的时候,Steve 回答说:

编程语言都是些令人惊讶的小动物,就像照料一头完全服服帖帖的宠物东北虎一样。你可能会以为你们两个会相伴的很愉快,但是对于那些诸如 Python、 Ruby 或者 JavaScript 这种富有表现力的语言来讲,如果你没有制定一套严格的纪律的话,它们说不定什么时候就会狠狠咬你一口。你必须要考虑那些要在你的环境下工作一段时间的临时用户,他们会有什么样的感受。限制语言的种类就是首先要做的事情,这样从内部来讲,每一个人就可以更容易的向他所喜欢的内部代码库提交代码(也就是用那 20% 的工作时间作的事情),而不必担心因为未知的语法而犯错。

在一个公司里,你需要为你“正式”支持的每一种语言付出很大的代价——要提供对基础架构的支持、文档、对开发人员的培训、代码冗余以及其他一些不利因素。编程语言都有一套众所周知的核心功能,但后面总是跟着拖着一条长长的模糊语义的尾巴,而这条尾巴会变得日益难以辨认。这个特点在那些没有实际规范的动态语言身上尤为突出,比如 Perl,Python,Ruby 还有它们同族的成员。Google 一直很谨慎的保持着开发语言的数量,把它限制在一个实用的范围内。这样我们就可以建立起一个庞大的专家组,而他们都是精通我们所选择的语言的。Google 的代码库一直保持得如此整洁和统一的一个原因就是, Google 已经在 C++、Java、Python 和 JavaScript 的基础上建立了标准,我们只能使用它们作为产品开发工作中的正式语言。这同时还有助于防止因为语言的互操作性而带来的组件之间相互组合的问题的遍地开花。

所以我没法用 Ruby。为了保证可以和代码库中的其它代码相互操作,我只能停留在 JVM 上(请相信我这一点——它根本不是我可以通过 RPC 调用来解决的问题;我必须要在 JVM 上运行)。由于这个利用,C++ 和(原生)Python 也被舍弃了。

针对选择 JVM 语言的话题,Steve Yegge 解释了他如何在 Java、Jython 和 Rhino 这几种语言中做出了选择:

在 Rails API 中,我们可以看到它的特色之一就是可以把散列表字面量(hash literals)作为参数传递,Java 根本就不可能做到这一点。Ruby 没有方法重载,而且 Ruby 和 Rails 都有着各种各样的惯例用来传递 varargs 或者 block(function)参数。Java 与 Ruby 的区别之大,完全可以让人因为障碍重重而放弃努力。所以我决定还是选一门动态语言。

Jython 在第一眼看上去的时候很明显是个不错的选择,但它从 2001 年起就没有什么进展了。它曾经是最好的非 Java 的 JVM 语言。Jim Hugunin 确实干的非常漂亮。但是不幸的是,在过去的六年内,它再也没有受到过任何宠爱,它已经远远滞后於 Python 好几个重要版本了(一个是 2.2,一个是马上要推出 2.6)。

相反,Rhino 一直都是人们的宠儿。它存在的时间甚至比 Jython 还要长,它一开始是作为 SpiderMonkey (Netscape/Mozilla) JavaScript C 引擎的移植,并且在开发的过程中就一直关注于性能问题。Rhino 代码读起来很像 C 程序:它避免过多的分配,并且尽量多地使用跳转表(Jump Tables)来避免虚方法查询(Virtual Method Lookups)的额外开支。它有两种代码执行方式:一种是无限循环运行的字节码解释器,一种是优化过的 Java 字节码解释器,可以把很多消耗资源的 JavaScript 属性查询转成 Java 局部变量或实例变量查询。Rhino 这个软件实现得非常严谨。

Steve 还对 JVM 语言做了一个总体上的评论:

你还要把语言和 JVM 实现的语义差异作为一个考虑因素。大多数的动态语言都没有特别严格的规范,而 JVM 实现和 C 的实现之间的差异也是没有文档说明的。我很喜欢 Rhino 的一点就是 JavaScript 确实有着一套规范(ECMA-322),而且 Rhino 做的最好的地方就是它把自己与 ECMA 的差异全都记录了下来(比如它的多线程语义)。但即使这样,还是有很多 JavaScript 与 Java 绑定的问题需要考虑,Rhino 有很详尽的文档说明,我们也还是花了很长时间来协同工作,来完成对边界条件的处理,并解决类似于类型映射和重载方法调用的问题。对任何一种给定的 JVM 语言,你所能找到的专家都要比对应的 C 语言实现的专家数量少的多。从这个角度来看,引入 JVM 语言要比引入它们原始版本的风险大的多,会抵消掉很多你从库的互操作性和 Java 支持的微架构上得到的收获。

Steve Yegge 已经在博客上发表了更多的相关信息,您可以访问他的博客,并请对InfoQ的相应报导保持关注。

查看英文原文:Steve Yegge Ports Rails to Javascript/Rhino

JavaRubyWeb框架Ruby on RailsJavaScriptGoogle语言 & 开发