Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2011-09-13) 魔幻的grails

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

今天尝试着使用grails来做一个小网站,感觉grails有点魔幻。虽然比rails好很多,但对于不熟悉它的人来说,还是经常让人摸不着头脑。

grails是基于groovy的一个web框架,它在相当大的程度上模仿了rails,同一种思想,同一种风格。要想快速入门,建议搜索一个叫“grails入门指南.pdf”的中文文档,短短70页,可以让人很快了解如何用grails开发。然后,新建自己的项目,开始。

在开发之前,准备好这几样:

  1. 下载STS:http://www.springsource.com/developer/sts

STS全称SpringSource Tool Suite,是由spring提供的一个基于eclipse的开发工具。其特色是集成了很多spring项目的插件,比如spring roo, groovy, grails等等。由于groovy被spring收购了,所以它提供的插件功能是最强大的(远比idea的要强)。要注意的是,grails插件并没有包含在里面,下载之后,点击其“extendsions”按钮,手动选中grails等插件,下载安装。

  1. Grails文档:http://grails.org/Documentation

找到其中的User Guide Pdf,这是一个官方提供的pdf文档,非常全面详细。因为grails大量使用了groovy的动态语言特征,导致IDE的提示功能有限,所以经常需要查手册。

  1. Groovy文档 http://groovy.codehaus.org/Documentation

里面有一些教程,以及Reference处有一些可供下载的资料。不知道为什么,我下载下来的chm打开后,内容全是“无法显示”

groovy的语法很灵活,开始的学习成本很低。因为它的语法风格与java非常相似,很多java代码直接拷到groovy中就可以运行。groovy提供的一些语法糖很不错,可以让代码写得很简洁。

groovy与java相比,语言特性可以分为这几个部分:

  1. 语法糖,简化代码

  2. 大量使用闭包,需要专门理解闭包的delegate机制

  3. 动态部分,这是groovy的特色以及难点

我们可以用groovy写出很静态的代码,看起来就像是简化了的java。比如,每个变量和方法,都标明类型,这种情况下,IDE的提示会比较准确。有一个groovy++的项目,就是将groovy代码编译为静态类型代码,以提高性能,它要求的写法,就是这样。我很喜欢这样,有安全感。

但是grails,作为ruby on rails的模仿者,当然是全力发挥其动态特性。这样,grails可以用很简洁方便的代码,快速实现功能。但也同样因为这个原因,如果你对grails不熟悉,特别是它约定的惯用法,就会觉得无所适从,无从下手。

举几个例子:

  1. 定义domain

class User {

String email

String name

String password

static hasMany = [ questions: Question]

static contraints = {

email nullable:false, blank:false, email:true, unique:true

name nullable:false, blank:false

password nullable:false, blank:false

}

}

这是一个简单的Domain,它做了很多事情:定义了一个User类,声明了各属性,它与Question之间的一对多关系,它的每个字段在保存(或验证)时必须满足的条件。

短短几行代码就做了这么多事情,开发效率果然高。但是,如果你不熟悉grails的话,就会觉得hasMany和constraints来得很突然。User类没有继承或实现任何接口,我们没法从代码中找到hasMany和constraints的来源(除非看文档),这是一种按名称事先约定好的惯例。只有靠看文档来熟悉这些。

  1. controller

class Users {

def create = {

def user = new User(params)

if(user.save()) {

[user: user]

} else {

render view: “register”, model: [user: user]

}

}

}

这是一个controller和action。注意,该controller同样没有继承或实现任何类,但是在create对应的闭包中,可以直接使用params这个参数(它表示得到的http参数)。为什么?我怎么知道这个params从哪儿来?除了它,我还能用什么?

答案在文档中。打开grails.pdf,搜索controllers,写得清清楚楚,我们在controller中,可以使用request, response, params, flash, servletContext, pageScope等等变量。但是如果没有文档写着,谁知道会有这些东西?

诸如此类,还有很多很多。要想熟练掌握这些,就必须先把文档看透,里面的知识点一个都不能漏,因为这些东西,你只能从文档中看到。还有多写程序,写多了就习惯了。同时多准备几个chm格式的api文档,groovy的,java的,grails的,放在手边经常查。因为很多时候,IDE都不能给你正确的提示,编译器也不会告诉你方法写错了,所以靠多查多背。

这里有必要讲讲,那些在controller中可用的,如params,request这些变量,到底从哪儿来。在groovy中,闭包被大量使用,比如上面的create就是一个闭包。闭包中有一个特殊的变量叫delegate,它默认指向声明该闭包的外部结构(如类或者闭包),但是它是可变的。当我们在闭包中写“params”的时候,它其实是指“delegate.params”。这一点,与javascript中的函数function中的this,非常相似。当我们写好一个闭包后,可以将任意一个对象赋给它的delegate变量,闭包在执行时,就会从这个新的delegate对象上去调用方法或拿数据。我们可以把闭包看作一个司机,而delegate是他要开的车,虽然他默认有自己的车,但你随时可以把别的车换给他开,甚至飞机,当然很可能机毁人亡(程序出错)。

这样我们就好理解了,肯定是在运行的时候,会将一个拥有着request, params, session等属性的对象,传给了这些action的delegate中,所以它才可以直接调用。但是我们是很难从代码中看到这些,除非你把grails的源代码下载下来,一点点地看。

对于像我这样长期习惯了静态类型以及IDE提示的人来说,grails还是相当地魔幻。当然不可否认的是,一旦熟悉之后,你将拥有非常高的开发效率(如同ruby on rails一样),但是在那之前,你需要花很长时间去猜测、理解它的惯用约定,以前多看文档和代码,并记熟常用的api。我还是非常想念静态语言开发的感觉(比如play),那种安心感,是让人非常舒适的。

我个人觉得,我们使用groovy不一定要全面使用它的动态类型。除去动态特性,groovy已经提供了比java丰富得多的表达能力。利用好这一点,应该也可以做出一个远比java中的那些web框架好用的groovy框架出来。在这种以静态类型为主的写法下,IDE的提示能力会比较好用,使用者也可以不必记那么多的东西,这已经是相当大的优势了。可惜的是,不知道为什么,在groovy世界中,好像除了grails,基本上找不到别的web框架了。

groovy++现在正在蓬勃发展之中,它写出来的代码,主要以静态为主。使用它,我们可以写出容易理解的代码来。不过似乎它现在还不够成熟,离正式使用还有一段距离。我想它发展起来以后,使用它开发的web框架,应该易学很多。最后还要提一下还未发布的Kotlin,我感觉它与groovy++很像,但是它将拥有很好的IDE支持,所以我非常期待它早日发布。

comments powered by Disqus