Top
首页 > 老文章 > 正文

基于Ruby On Rails开发高品质Web应用

文章将逐一探讨多个影响Web使用质量的要素,同时希望读者们可以从中领悟到Rails为创建高质量的Web应用程序的特性,和Rails的各种设计给我们的启示,以及Rails 3的改进所代表的意义和趋向。
发布时间:2010-08-17 09:36        来源:        作者:51cto
我们都知晓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 << Photo.new params[:album][:photo]   ... 
假设是一个触及更多品种型对象的表单,这里的代码能够会愈加庞杂。但在AlbumsController内部,我们真实想关心的只是Album的创立,而不是Photo或其它关联对象的创立。并且从Album的角度看,创立流程中photo跟其它attributes没有区别,应该得到一致地处置。Rails 2.3之后,我们就能够很容易地抵达这个目标。在Album内部做这样的声明:
class Album < 
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 => ' application/pdf')   end 
<System.Web> 
<httpRuntime maxRequestLength="10240" /> 
</System.Web>
这段代码至少存在两个疑问:第一个疑问,就是我们先面所述的职责明白疑问。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 => @invoice.pdf  }    end  end 
<System.Web> 
<httpRuntime maxRequestLength="10240" /> 
</System.Web>
重写之后的代码不只更契合REST的作风,并且愈加简约优美。 JavaScript 随着RIA的普及以及时代的即未来临,JavaScript的江湖位置正在与日俱增。从Google的一些使用就能够看出业界关于 JavaScript态度的一些改动。比如Gmail,它提供了在无JavaScript支持环境下的普通版本和有JavaScript支持的全功用版本 ──这是一种渐进式加强的设计理念。但随后几年推出的Google Doc,曾经完全丢弃了对无JavaScript环境的支持。从这些改动能够看出,JavaScript曾经是Web使用的“必需品”。甚至有人把 JavaScript称为当今最首要的编程言语,从某种意义上这种说法也不过火。 很久以来,我们不断以“脚本”的态度看待JavaScript。顺序员对JavaScript的注重水平很不够,业界对顺序员的JavaScript才干要求也不高。如今,必需做出这种态度的转变。Rails 3所做的很大一个改进就是:Unobtrusive JavaScript(非侵入式的JavaScript),以完成对HTML和JavaScript代码的别离。比如:
<%= link_to "delete", 
album_path(@album), 
:method => :delete, 
:confirm => "Are you sure?"%> 
在Rails 3之前,它生成的代码应为(代码举行了省略):
<a href="/albums/1" 
onclick="if (confirm('Are you sure?')) 
{       
var f = document.createElement('form');      
 f.style.display = 'none'; 
this.parentNode.appendChild(f);
f.method = 'POST'; ... 
能够看到,生成的HTML内嵌了大量的JavaScript代码,这是一种不好的做法。Rails 3所做的其中一个改动,就是别离HTML和JavaScript代码,生成的HTML中内嵌的JavaScript代码消逝了:
<a href="/albums/1" 
data-confirm="Are you sure?" 
data-method="delete" 
rel="nofollow">delete</a> 
那么JavaScript代码到哪里去了?它们都被放到了一个叫做Rails.js的文件中。跟服务端MVC要求职责别离一样,这个准绳也应该表如今客户端的代码上。HTML、Css和JavaScript应该职责明白地各自傲责数据、显示和行为。同时,这种别离也对顺序员的JavaScript才干提出了更高的要求。 功用 从一个央求(Request)的数据传输角度看,数据普通会阅历从数据库到服务器,结尾到客户端这么一个流程(能够尚有其它层次)。数据离客户端越近,照应速度必须越快。因而,缓存是提高功用的一大利器。 而客户端缓存是离用户近来的地点。关于客户端缓存的一条准绳是:不要缓存静态HTML页面,但长久缓存一切其它文件类型。Rails对静态文件的处置很好地表现了这条准绳。比如下面这段代码: stylesheet_link_tag("application")  它生成的HTML是:
<link href="/stylesheets/application.css?1232285206" 
media="screen" rel="stylesheet" type="text/css"/> 
其中application.css?1232285206的后缀是这个文件的时间戳。那么客户端就能够不担忧肠长久缓存这个静态文静。由于文件一旦更新,客户端就会以为这是一个新的央求,即会去获取最新的文件。 Rails还在其它许多方面提供了简便的办法使功用优化变得容易,比如服务端缓存机制等。但大非少数时分,功用疑问源自于我们自己的完成或许设计疑问。比如关于Active Record Query Interface的的滥用,非少数时分功用疑问都能够议决齐备数据库查询来得到很大的改进。关于数据库查询,我们应该经常重视多个疑问,比如:获取的数据后果集中能不能有大量无用数据,数据库查询次数能不能能够降低等等。 用户体验 用户体验是Web使用十分首要的元素,Rails作为Web开发的DSL在这方面也有许多重视。 在Web使用中我们经常遇到的一个疑问是:submit button(提交按钮)被屡次点击。假设没有被恰当处置,就会惹起表单的屡次提交。用Rails的form helper办法能够很容易地防止这个疑问: submit_tag "Submit", :disable_with => "Submitting..."  代码中的:disable_with选项的作用是:在button被点击之后把它disable掉,并且把button的文字交流成“Submitting”。一个容易的选项带来了显而易见的益处:不只防止了屡次点击的疑问,并且显式地通知了用户表单正在被提交当中。 Rails提供了许多便捷的办法,让提高用户体验变得十分容易。作为顺序员,我们也应该对用户体验有更多重视,比如如何设计更好的交互来防止AJAX所带来的种种用户体验疑问等等。 安全 Web使用面对着许多安全隐患,比如Session定置(Session Fixation)、跨站央求伪造(CSRF)和日志信息泄露(Logging)疑问。在Rails中我们能够用容易到只需一行代码的方式来防止这些安全疑问。下面是各安全隐患以及对应战略。 Session定置 攻击者议决某种方式强迫用户运用他所掌握的Session ID,在用户登录之后攻击者即可运用此Session ID窃取用户的信息。处置方案: reset_session  在登录逻辑中添加此段代码,以在登录之前重置session,这样便能够防止攻击者议决Session Fixation攻击来获得用户信息。 跨站央求伪造 CSRF是指在页面中注入一些歹意代码或许链接──指向用户运用的其它站点,比如站点A。当用户访问被净化的页面时,假设刚好站点A仍处于有效认证期,则用户在站点A的数据就会被侵犯。处置方案: protect_from_forgery :secret => "123456789012345678901234567890..."  此代码会在非get央求中添加一个security token,假设token不一致,则央求将失败。这种方式能够有效防止CSRF,当然前提是我们正确地运用了HTTP method。 日志信息泄露 默许情况下,Rails会把一切的央求信息都记载在日志文件中。那么攻击者就能够议决窃取日志文件,以得到一些秘密信息,比如登录密码、信誉卡信息等等。处置方案: filter_parameter_logging :passWord  这行代码就能够过滤那些不期盼被日志文件记载的信息,比如password等,从而防止议决日志来泄露敏感信息。 Web使用还面对着许多其它安全疑问,比如SQL注入,XSS等等。我们应该更多重视Web使用所面对的安全疑问,并尽能够防止。何况,在Rails中要防止大非少数疑问,办法都很容易。 业务模型 结尾一个疑问虽然与Rails甚至技术的联系并不大,但是却联系到一个Web使用质量的最首要疑问:创立的Web使用能不能契合业务模型。我们以前在一个电子商务使用的开发流程中遇到这么一个疑问:整个购置流程的结尾一步是破费页面,用于完成破费并生成收据的PDF文件。产品交付之后,客户开端埋怨破费页面的功用疑问:照应时间超越了容忍度。于是我们试图改进破费页面的功用,但由于破费页面触及的逻辑和业务真实过多,功用提高很难处。 但当我们重新审视破费页面的业务逻辑时,我们发觉这个页面原本包含了两局部功用:破费和PDF文件的生成。而从业务角度看,PDF文件的生成不属于破费流程,而是破费完成之后的逻辑。并且,并不是一切的用户都须要生成PDF,强迫在破费的同时生成PDF是一种资源的糜费。所以,我们把破费页面举行了拆分:把生成PDF文件的功用移到了破费成功页面,并且只需在客户点击相应链接之后才会生成PDF。容易的改动之后,不只功用疑问得到了处置,并且使用也愈加契合真实的业务流程。 当我们遇到疑问或许举步维艰之时,停下来思索一下:我们对业务的明白能不能出现了疑问,我们的设计能不能出现了疑问。许多时分我们都能够在这里找到答案。重新思索业务逻辑或许重新设计之后,完成能够会容易许多,甚至也许疑问本身都曾经不复存在了。

(实习编辑:HJ)

加载更多

专题访谈

合作站点
stat