BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Yehuda Katz谈Rails 3.x
录制于:

| 受访者 Yehuda Katz 关注 0 他的粉丝 作者 Ryan Slobojan 关注 0 他的粉丝 发布于 2010年12月6日 | 如何结合区块链技术,帮助企业降本增效?让我们深度了解几个成功的案例。
29:39

个人简介 Yehuda Katz目前受雇于Engine Yard,全职作为Rails项目的核心小组成员。他是《jQuery in Action》和即将出版的《Rails 3 in Action》的合著者,同时他也是《Ruby in Practice》的供稿人。他的大多数时间都花在钻研Rails和其他一些Ruby社区项目上,比如Rubinius和Datamapper。Katz 的其他项目还有Thor和DO.rb。

Strange Loop是一个开发者组织的软件大会。改革、创新与未来就发生于既定领域“之间”那不可思议的关系之中。Strange Loop在这一关系中积极推动语言与技术的混合,集合世界最尖端的技术、企业级系统和学术研究成果。尤其关注于数据存储、替代语言(alternative language)、并行及分布式系统、前端Web、语义Web和移动应用这些方面的新动向。

   

1. Rails 3是如何被社区所接受的,其中最常用的特性是什么?

我非常满意目前的接受程度。Rails 3是一个重大版本,我们为之奋斗了好久,我们真正担心的问题不是与现有应用程序的兼容性,而是与现有插件的兼容性。我觉得,有件事我们做对了,那就是我们有一个相当长的Beta阶段,接着是RC阶段,最后是正式版,这让很多最常用的插件得以针对Rails 3进行更新。几乎你可能用到的所有东西都更新到了Rails 3或者有一个针对Rails 3的替代插件。

也许不是每个Rails 2.3.*上的应用程序都升级到了Rails 3。但我可以说大多数人现在是用Rails 3来创建新应用程序的,实际上我没有听说过谁还在用Rails 2.3.*来创建新应用程序了,所以说这真的很令人兴奋。我们还在2.3.*系列里做了不少工作,2.3.*的应用程序随着你的升级会出现越来越多的警告,其内容是关于那些Rails 3中发生变化的东西。其中,最有用东西之一是XSS插件,它能防止跨站脚本攻击,它在Rails 2.3.*中的工作方式与Rails 3是一致的,其次是Rails 2.3.*中的Bundler支持。

那些可能就是升级到Rails 3之前应用程序中发生的最大的变化了。如果你是沿着2.3.*系列的金色大道一路升级上来的,那么升级至Rails 3就只是依次搞定你的插件而已。正如我所说的,社区真的就是这么开始着手去做的。在最常用的特性方面,人们讨论最多的东西可能就是ActiveRecord语法了。在将代码放置在何处方面,我们把ActiveRecord修改得更灵活了。以前是这样的,如果你把代码放在Model类里,你要将代码放在Model方法中;如果放在Controller里,那些语法是不同的,这要求你了解所有的东西,比如名称、作用域等等。

在Rails 3里,那些东西的语法在所有上下文中都是一样的,这样一来你可以很容易地说“哦,我在Controller中用了很多这玩意儿,它们和我准备要移入类方法或作用域的东西是一样的,而且代码看上去也是一个样的。”我想很多人都喜欢这样。我目前正在做的东西,是我在自己的应用程序中广泛使用的,就是Rails 3从前面所说的上下文一路到ActionController构造Controller的方式。这对性能很有用,如果你正在构造一个对性能有严格要求的应用程序,这能让你更方便地选出Controller中很慢的特性,与此同时还可以继续获得紧密集成带来的好处,获得你所需要的特性。

一般来说,就像你在API Controller里不需要呈现页面一样,你可以修改一下把这部分移除出来,同时仍然能获得普通Rails路由和Controller(有条件GET)所带来的好处。有了路由后,很多人就讨论说要试着把它移植回2.3很困难,但这路由真的很强大而且很独立。你可以把它用在Sinatra应用程序或别的什么东西上,我对API进化的方式感到非常满意,基本上使用了Rails 3的路由后,没什么事情是做不了的。它支持任意类型的路由,支持任意你希望设置在路由上的规则,在这一点上Rails 2.2的路由真的非常局限于通用Rails使用模式。因此,这点让我很惊喜,我想很多人也在讨论这一点。

   

2. 自从Rails开始流行起来以后,其他语言也开始效仿Rails的思想,例如Groovy和Grails。其他语言里也有类似的东西。你有看到这些从Rails中得到灵感的框架采用Rails 3的一些特性,或者规划一些更高级的特性吗?

这很难说,是有些很像Rails的框架,例如Symphony,但它们没有使用像Ruby一样灵活的语言,所以它们并没提供相同的特性集,它们是将特性集硬编码进PHP的。我最近刚看了Symphony,基本还是只有Rails 1.x的特性。也许他们不知道,也许知道(我不太清楚),但他们实现这些特性的方式让他们无法轻易做出改进。无论复制的是哪个特性都做硬编码,然后去复制另一个特性,这很复杂。而Rails使用的是Ruby,更容易对特性集做平滑升级。

我觉得Grails与Rails的特性集更接近一些。依我的口味,Grails的路由很丑陋。它有一些Rails 2.3都没有的特性,但我认为Rails 3的路由无论在表达能力还是特性上都是最强大,也许能和nginX或Apache Rewrite相媲美,特别是它的语法易于使用,支持任意Ruby代码。你可以用相当简单易懂的API写出各种想要的rewrite。这其实与Rails 社区有关,这才是我在回答这个问题时想要说的。

Rails社区相当关注开发者的可用性,这意味着Rails社区不接受那些不够格的API。一个例子就是Rails 3添加了Bundler支持,我在这块花了很多时间。Bundler真的很好用,但Rails社区一直把它推回去继续打磨,直到所有边边角角的问题都搞定为止。如果你把它和Maven(一个类似的API)这样的东西相提并论,差不都所有用过Maven的人都知道使用Maven就是一个噩梦。这不仅仅是复制特性这么简单。当然,Grails可以复制Rails,Symphony可以复制Rails,K PHP可以复制Rails,但这些社区并不能像Rails社区那样迫切地想构建出好用的特性集和API。

他们从直接将Rails代码迁移进他们的语言中获得了可用性,但很多关于 API的东西却感觉更糟糕了。你可能会注意到Grails硬塞了很多特性进去,看看Grails的Model中hasMany是怎么工作的,就好像是定义了一个属性,其中有很多某个东西的数组。类似的,Symphony有“var hasMany = 某个东西的数组”,比起Rails的做法,它不太友好。如果要说综合体验,你会发现这些东西都加到了一起。在一些情况下,这种表现很极端,比如说 Maven,这是个极端的案例,但就算在常规特性中情况也是一样的。

关于这个问题,我还要最后说一点,Rails中有一些东西,尤其是REST风格支持是贯穿在整个框架中的。在以前,我们说这个东西实在很有用,但基本上来说REST API并不仅是POST东西、PUT东西或DELETE东西。REST API意味着框架中的各个角落里都支持REST风格,从ORM返回的对象可以变成URL,你可以可以重定向到对象。几乎框架中放入的东西都有REST风格支持,其他框架并不在乎这个。

看看Grails的REST支持,其中允许路由来路由一个PUT请求——这是一种REST支持,但却不能链接到一个对象,重定向到一个对象,或者为一个对象创建表单。有一些硬编码的情况,但Rails却是通用的,整个框架基于一些惯例,这能改善代码的可用性。

   

3. 你是说Rails的抽象程度更高一点吗?

我只能说Rails一贯想让抽象的程度更高一些,所以基本上你都不用在Rails中写URL,这并不是因为我们在背后做了什么疯狂的事,当你在写ORM对象时,Rails 3包括MongoDB、DataMapper和SQL ORM——这些都是ORM。有一个可以给你自己去实现的API,替你生成URL。然后你只需要说“用户是资源”,在整个框架里,你就可以重定向到对象,链接到对象,以及呈现对象。

到处都是这样的惯例“你想呈现一个用户?——这是我们去找模板的地方。”随着你的成长,此类惯例并不会优待你。你到底该把模板放哪里这样的问题并不重要,大多数人不想花精力去回答它,那你又为什么要去考虑它呢?我觉得你可以把惯例优于配置说成一个通用概念,你可能会说“这不能用于大应用程序。”于是你开始钻研,去看每一个细节的配置,你该如何命名特定方法,将特定类型的模板放在何处,在资源Controller的路由中该怎么做。

所有这些内容并不是真要强制你去遵循某条特定的惯例,我们是在替你回答那些烦人的问题。当你开始写应用程序时,不需要和整个团队坐在一起去决定 Controller中的POST方法。基本上没哪个应用程序需要讨论此类问题。无论应用程序是大是小,复杂还是简单,在每个应用程序中,目录该如何布局,方法该如何命名,对于那些常见情况来说,这些都是不需要讨论的。

Rails 在这方面做了很多工作。就好像30秒片段版,Rails比其他大多数框架考虑得都多,大多数框架甚至都不考虑这些东西。当你看其他框架时,你会发现他们复制了足够多的东西去做一个50分钟的博客视屏,拥有脚手架生成器。当你问道“我能链接到一个对象么?”突然没人考虑过这个问题。那是因为他们并没有真的仔细了解过Rails在做什么。

   

4. 不断增多的Ruby实现,例如JRuby、Rubinius,是如何帮助Ruby和Rails得到社区认可的?这带来了什么好处?

首先,我想说Rubinius团队和JRuby团队真的很努力地投身于RubySpec项目之中。Rubinius团队先开始了这个项目,然后JRuby团队很快加入其中。RubySpec是一系列可执行的规范,通过运行它们来证明你用的是Ruby。并不是要你遵循某些正式的规范,而是看你是否能执行这些测试。当然,根据定义,CRuby一定是能运行的。如果你用CRuby来运行测试,结果失败了,那有问题的是这些测试,而不是Ruby。

让人兴奋的是Ruby 1.9团队做了很多工作,让RubySpec针对Ruby 1.9也能有意义,你可以用一个兼容Ruby 1.9的实现来运行测试,看是否通过测试,为类似编码这样的Ruby 1.9新增的特性增加一组测试。我认为在谈论多种Ruby实现之前,我们应该感谢那些为RubySpec做出贡献的人,他们持续不断地投入 RubySpec,为的是让JRuby和Rubinius可以完整运行Rails。Rails是奋斗的目标。当你开发一个Ruby实现时,你应该期望它能运行Rails。MacRuby可以跑很多Ruby程序,但它目前还不能跑Rails。

在你运行Rails时还需要做一些更细致的步骤,当然,你可以做些事情来看一看是否可以运行标准库等等诸如此类的。但能够运行一系列测试,判断你是否可以运行Ruby变得越来越重要了。我想说JRuby的兼容程度几乎是100%,他们做的工作中有很大一部分是RubySpec,自己还写了很多其他测试。在人们为Ruby语言构建的多种实现中,我觉得它是最兼容的,JVM很不错。Ruby的实现,至少Rubinius、JRuby和CRuby彼此兼容,这点很好。

说到让人接受Rails这点上,JRuby还真帮了不少忙。很多人并不知道JRuby其实是一流的实现,它不像Jython,可以用但不是最新的,它是 Python 2.5,有一些特性是不支持的。JRuby力争成为一个与当前Ruby兼容的实现,你需要在脚本中requrie "java"才能启动新的Java集成特性。通过require "Java"你可以获得一组特性,如果不这么做,那么它就是一个与CRuby兼容的Ruby实现。这是Rails在JRuby上能顺利运行的重要原因。

社区里还有些别的东西,比如支持Java这样的平台的Ruby Gem系统、JRuby在C扩展上的不断努力,这都在不断推动它的发展。JRuby与CRuby的兼容性意味着我们无需在Rails中花太多精力让它运转起来。JRuby社区在Rails兼容性方面也做了很多,针对一些有问题的测试提交补丁。也许这些测试需要以某个特定的顺序运行,这不是JRuby的问题,是我们测试的问题。

有些情况是这样的,他们提交了一些补丁,但总的来说Rails能运行在JRuby里对于更多的企业社区采纳Rails来说是很重要的,我不喜欢企业社区这个词,可是对于那些已经拥有Java基础设施的人来说,他们更愿意这么做,我觉得Python的人就不会。我觉得JRuby正逐渐变为一个好的解决方案,哪怕只是用来部署Ruby应用程序。

需要高并发性的人从JRuby中看到了不少好处,以及围绕JRuby建立起的生态环境。讲到Rubinius,他们的1.0版本与MRI兼容,性能上又和 Ruby 1.8相接近,他们也继续在性能方面下功夫。在我看来,Rubinius最终将成为最快的Ruby实现,但要走的路还很长。他们的VM对Ruby来说很高级,也许这是我们拥有的最高级的纯Ruby VM。因此我不会把Rubinius和JVM相提并论,但就VM的Ruby部分的“聪明”而言,Rubinius也许是最聪明的,他们可以做到内联块,内联方法等别的Ruby实现做起来很困难,CRuby不做的事。

我希望Rubinius能有越来越聪明的VM,这将把它推向第一位。届时,你会希望去使用它,因为它提供了更多的信息、更多的自省能力,我想 Rubinius也会继续沿着这条路走下去的。关于哪个实现是最好的实现,一定会有一场竞争。我认为就目前而言JRuby是最好的Ruby实现,但每个人都想占据一席之地。

   

5. 在即将发布的Rails 3.1中会有什么改变吗?

当然会有!我们就此做过一些讨论,明确目前要做哪些东西,不做哪些。过去的几年里,客户端需要越来越聪明的asset编译,为此使用SCSS或Coffee Script,串联(concatenation)、放大(magnification ),以及其他编译技巧变得越来越常见了,到目前为止很多东西依然以插件的形式存在着。在Rails 3.1里,assest就是一级对象,它们有自己的编译管道,有自己的模板概念,无需独立的编译步骤就能在服务器上运行,可以在运行被编译及缓存。

所有这一切都在Rails 3.1里,基本就是说我们对SCSS会有一流的支持,包括sprite和Compass,它提供了CSS3支持,不用再写那些破折号了-webkit,还有其他一些很棒的东西。基本上我们将拥有一流的SCSS支持,大体说来就像编译管道,如果你不想使用SCSS,或者你不想使用JavaScript编译,我们有简单的特性,比如仅依赖JavaScript文件或放大。无论你正使用一个高级编译器,例如SCSS,或者是你想做点简单的事,你只需要通用特性。这些东西都会在Rails 3.1里。

在Rails 3.1中我们还在HTTP缓冲方面下了不少功夫,我们之前就有开启HTTP缓存的特性,但很多人没有使用它。部分原因是HTTP缓存的唯一用户是独立的客户端——Web浏览器,如果你有一千个用户,这无济于事,每个用户仍旧会带来大量HTTP缓存,因此人们会用其他技术,例如片段缓存或页面缓存,来代替 HTTP缓存。我们在Rails 3.1中带了一个rack-cache,这是一个内建的缓存层。

rack- cache能让你更智能地使用HTTP缓存,让它能和页面缓存、action缓存或片段缓存一样得到重用。在某些场景下,这意味着以稍微不同一点的角度来考虑你的应用程序,但同时我们也让你能够在无需重写你的缓存层的前提下,使用SQUID或Akamai这样的缓存服务器来提供HTTP缓存。所以如果你买了Akamai,你的应用程序已经可以利用Akamai提供的特性了,因为我们内置了对它的支持。关于rack-cache,我还要补充一下,当人们第一次听说它的时候,都觉得rack-cache会在堆里完成全部的缓存,在Ruby堆里,其实rack-cache要比这聪明的多。

它可以使用memcache、文件系统或者redis。在Rails 3.1中,无论你的Rails缓存是什么,都可以用rack-cache。也就是说如果你的Rails缓存是memcache、redis或文件系统,都没问题。这意味着Ruby中会有一定量的逻辑来验证缓存,其中开销最大的一块是所有这些大文件最重要放在更合理的地方。这很让人兴奋!

我们还不打算把flush放进Rails 3.1,用自动flush的主要原因是在flush时会有很多警告,我们还要考虑一下,也许Rails 3.2版时会认真考虑这些问题的。可能会做一个插件开启该功能让大家先玩一下。ActiveRecord在使用该功能后得到了不少性能提升,我们正在改善性能。通过Ruby Summer Code项目,我们正打算为Rails 3.1加入Identity Map。引擎上也做了很多改进,因此你可以更方便地构建一个Rails应用程序,随后再弄引擎。

有不少Ruby Summer Code项目,以及社区贡献的特性也会在Rails 3.1中占一席之地。关于Rails 3.1,我想说的是我们对Rails 3.0的基础设施做了很多工作,3.0中有很多很棒的特性,比方说ActiveRecord、Action Mailer还有路由,Rails 3.0实际是在改善内部设施。

Rails 3.1利用了这些改进后的内部设施,有大量新特性我们是想放进3.0的,但我们总得发布吧。大量Ruby Summer Code项目,大量社区贡献的东西,更好的通道处理。我想类似HTTP缓存之类的东西也许还是在日后出现会更有意义。HTTP缓存是一个与REST类似的赌注,追溯到Rails 1.2中,“REST对请求而言是有意义的”,而在Rails 3.1中,“REST对发起者是有意义的”。虽然最初的工作可能比较粗糙,我们只是加入缓存支持,清理了一下现有的缓存相关的东西,我相信随着时间的推移,会形成额外的惯例,让HTTP缓存变得更好。

总的来说,能让HTTP缓存变得更好,在Rails 3.1中加入缓存层让我很兴奋,我很想看看人们用它来做什么。发布这个功能是一个赌注,它会很有用的,就像类似的在3.0、1.1和1.2里的工具一样。

   

6. 有很多出现时间比较长的框架,第一个映入眼帘的是Java EE,第二个是Spring,总有这样的情况,1.0刚开始时框架相对较小,随着它的发展,你会得到一些特性,当时它很有意义,但后来又没用了。人们开始抱怨代码膨胀或者功能膨胀,或者别的什么。Rails 3是怎么对待这个问题的?开发计划中如何应对它,避免类似的事情发生?

实际上我们做了很多工作来应对这种情况。Rails 3.0中的一个重大改变就是我们开始更多地使用社区以来。我们用Bundler项目取代了自己写的gem。我们用了rack-mount项目来取代特定于 Rails的路由,它允许任意rack框架使用我们的路由。我们帮助Michael开发mail gem,这现在已经是一个功能完整的gem了,我们不再继续维护自己的邮件框架,即team mail项目。我们做了很多类似的事情,把原本硬编码在Rails里的东西提取出来,这样一来那些在该领域更专业的人可以帮忙维护它们,Rails项目能变得更小。

我们还话了很多时间来思考Rails框架本身并不需要如此耦合。举例来说,以前ActionPack中到处都是对ActiveRecord的依赖,在 Rails 3.0里我们去掉了这些依赖,在Rails中创建了一个名为railties的新层次,它是Rails所需要的那部分ActiveRecord。我们既有 ActiveRecord,又有作为Rails一部分的ActiveRecord,我们将它们分离了出来,有作为Rails一部分的 ActiveRecord、ActionMailer、ActiveResource以及ActiveModel,我们把这些东西移到了单独的地方。这样一来如果有人想自己使用ActiveModel,他就不用折腾整个Rails了。这曾经是一个很让人受打击的问题,以前如果有人想用 ActiveRecord或者是ActionMailer,他们不得不引入很多Rails的东西,他们会发现自己用了很多MB额外的内存,用到的代码超过他们的预期。

在ActiveSupport中也有类似的问题,它应该是一个静态库,以前为了获得某个功能,你必须载入所有的东西。在Rails 3.0中你只需要载入特定文件,就像标准库一样,你只需要载入那些文件就可以了,不许要载入所有的东西。总的来说我们在模块化上下了很多功夫。

在Rails 3.0中我们花了很多时间来思考Rails的部分功能,我们在REST上下了赌注,Rails 1&2直到3.0我们还没彻底清理干净REST之前的东西。我们花了很多时间告诉大家“如果你不想使用REST,那么也许你不该用Rails”。我们要清理掉很多此类内容。我想这是不可避免的情况,一个项目存在的时间越长,就有更多的用例冒出来,项目越变越大。我们在Rails 3.0里思考了很多,显然这些特性的存在是有自己的理由的,但如果你想构建一个更小的应用程序,你该怎么办?如果你不许要这些特性,该怎么做?

我很高兴地说我自己正在我自己的项目中使用这些功能,也许现在该说是我公司的项目了。我们在ActionController::Metal上做了很多工作,它就是为了除去多余的东西而设计的,我们做了不少事来移除框架中我们不想要的那部分,在Rails 3.0之前我们是没有办法做得这么激进的。至少对我来说这很有用,我希望能有更多的博文来阐述如何做到这一步,我自己写了不少,但我希望看到更多的人谈论 “如果你不想要整个Rails,你该怎么做呢?”

   

7. Rails 3.1最终版的时间安排是什么样的,基于这个安排Rails 3.0.2的工作又该如何开展呢?

Rails 3.1很有希望在年底发布,我不能保证,但这是我们大致的发布时间。可能会有点延期,我们正锁定Rails 3.1的功能集,就像我前面告诉你的,差不多我前面说到的特性不是已经有了,就是正在积极实现中。我相信很快就能看到RC版本,随后就是3.1的正式版。

我很高兴地告诉大家,我们在Rails 3.0.x(3.0.x的分支)上做了很多工作,自从3.0发布后有超过100次的提交甚至更多,ActiveRecord上也有很多很积极的工作。大家可能知道在我们发布Rails 3.0时我们知道它有些性能问题,基本上它跑的还行,不像人们运行Microbenchmarks时看到的那么糟糕,但在性能方面肯定还有能做的事,AT&T的Aaron Patterson花了很多时间改进ActiveRecord底层的ActiveRelation库。最终他做到了,Rails 3中的大多数查询会比Rails 2.3里快不少。

我想这个可以放在3.0.2里,我们不必等到3.1发布,如果我们有时间这会放在3.0里,但我们总得发布吧。我很高兴看到在3.0.2里解决一些大问题,此外很高兴看到有这么多社区参与其中。

有一件事让我感到很满意,Rails项目的频繁贡献者数量有了很大的提升。正如我所说的,自3.0发布后我们有100次甚至几百次的提交。我甚至不敢相信, “哦,我们差不多该发布3.0.1了,我和你打赌这是一个小升级”,然后我看了下提交情况,有很多提交。当然,3.1的分支上的提交更积极些,但就算是 3.0分支上的不太积极的部分也有很多提交,其中很多都是来自社区参与者。我很感谢AT&T,还有其他人投入自己的工作时间在Rails项目上,这让我很兴奋。

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT