越来越多的企业开始选择Rails作为Web应用的框架。Rails曾经还主要是一些轻公司的选择,但今天一些“重”企业(比如保险、金融等行业的企业)也开始把Rails纳入内部应用甚至外部应用的考虑范围。我最近服务过的客户是国外某大型保险公司,该公司就选择了Rails来创建他们的保险销售网站。
\选择Rails的原因,是因为它快速构建的能力,是因为它是Web开发的DSL。但是否选择了Rails就代表了高效开发?是否在Rails上创建的Web应用就一定是高质量的?答案是否定的。从我参与过的几个Rails项目来看,质量可谓是参差不齐,开发速度也是判若云泥。而开发的效率低下的原因,则常常是应用本身质量的低下和设计的拙劣。
\在本文中,我将逐一讨论几个影响Web应用质量的因素。同时,我们也可以从中领悟到Rails为创建高质量的Web应用所做的努力、它的各种设计给我们的启示,以及Rails 3的改进所代表的意义和趋势。
\MVC
\我们都知道Rails是一个MVC架构模式的Web框架,MVC各部分的职责也很清楚。但问题在于我们是否真的遵循了MVC架构模式做到了各部分职责的明确分离?是否遵循了单一职责的原则?
\在大多数代码里面,这种混沌不清的状态存在于model和controller之间:controller承担了太多本应由model承担的职责。其中比较典型的例子是内嵌(多)对象表单。比如,Album和Photo之间是一对多的关系,我们要创建一个含有多个photo的album。在Rails 2.3之前,我们可能会写出类似的代码:
\\AlbumsController\ def create \ album = Album.new params[:album]\ album.photos \u0026lt;\u0026lt; Photo.new params[:album][:photo]\ ...\\
如果是一个涉及更多种类型对象的表单,这里的代码可能会更加复杂。但在AlbumsController里面,我们真正想关心的只是Album的创建,而不是Photo或其它关联对象的创建。而且从Album的角度看,创建过程中photo跟其它attributes没有区别,应该得到一致地处理。
\Rails 2.3之后,我们就可以很简单地达到这个目的。在Album里面做这样的声明:
\\class Album \u0026lt; ActiveRecord::Base\ ...\ accepts_nested_attributes_for :photos\end\\
然后,controller中的代码就可以被简化为:
\\AlbumsController\ def create \ album = Album.new params[:album] \ ...\\
从这个例子中可以看到Rails在推进MVC三部分之间职责明确上所做的努力和进步。很多人可能会说,我们的代码没有这样的问题。但MVC三部分之间职责开始模糊,往往出现在业务逻辑变得复杂之后。我们应该经常审视我们的代码,做到真正的职责单一。
\REST
\现今的互联网应用已经很难是一个独立的个体,互联网应用之间的交互越来越多。所以,建立REST架构风格的互联网应用变得越来越重要。Rails的router很好地支持了REST风格的外部接口设计。Rails 3所做的一个很大改进就是router的改进,以强调REST风格的接口设计。
\REST也让我们以资源的角度看待应用中的数据,我们的代码设计因此也产生了一些变化。当需要增加一个invoice的PDF文件下载功能的时候,我们一般会向InvoicesController添加这么一段代码:
\\InvoicesController\ def download_pdf\ ...\ send_data(generate_pdf(@invoice), :type =\u0026gt; 'application/pdf')\ end\\
这段代码至少存在两个问题:第一个问题,就是我们前面所述的职责明确问题。PDF的generate属于Invoice而不是controller的职责,所以我们应该把PDF生成的逻辑移到Invoice内部。第二个问题,则是语义是否恰当的问题 。如果我们以资源的角度看待Invoice的话,PDF跟HTML或者XML一样,只是Invoice的另一种表现形式而已。而表现一个资源,在show action中处理最为恰当。
\重写之后,代码如下:
\\def show\ ...\ respond_to do |format|\ format.html\ format.pdf { render :pdf =\u0026gt; @invoice.pdf }\ end\end\\
重写之后的代码不仅更符合REST的风格,而且更加简洁优美。
\JavaScript
\随着RIA的普及以及HTML5时代的即将来临,JavaScript的江湖地位正在与日俱增。从Google的一些应用就可以看出业界对于JavaScript态度的一些变化。比如Gmail,它提供了在无JavaScript支持环境下的普通版本和有JavaScript支持的全功能版本──这是一种渐进式增强的设计理念。但随后几年推出的Google Doc,已经完全放弃了对无JavaScript环境的支持。从这些变化可以看出,JavaScript已经是Web应用的“必需品”。甚至有人把JavaScript称为当今最重要的编程语言,从某种意义上这种说法也不过分。
\很久以来,我们一直以“脚本”的态度看待JavaScript。程序员对JavaScript的重视程度很不够,业界对程序员的JavaScript能力要求也不高。现在,必须做出这种态度的转变。
\Rails 3所做的很大一个改进就是:Unobtrusive JavaScript(非侵入式的JavaScript),以实现对HTML和JavaScript代码的分离。比如:
\\\u0026lt;%= link_to \"delete\