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

(2013-05-24) Lift小记

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

我参与一个Lift的项目已经三周了,现在的程度是基本上能用了。它的流程、原理等基本了解,可以独立实现一些常用的功能,但考虑到Lift处处是坑的现状,要用它做一个完整的、功能较复杂的网站,可以肯定这决不是一件容易的事。

(注:随着项目的深入,发现了lift一些真正有趣的地方,改变了我的看法。也许到项目结束时,会有全新的认识,到时候再记录一下。本文你可以看作是一个初学者刚尝试lift时不深入的看法)

按我目前所感受到的,lift有以下特点:

  1. lift的安全性极高。比如form/input等,它们的name都是临时生成的,每刷新一次页面都不相同,这样让人无法通过伪造post请求来侵入系统。
  2. lift内置了ajax支持,我们可以不用手写js代码,就能实现单页程序。让一个页面元素产生ajax调用、取得数据再局部更新页面,是一件非常容易的事
  3. lift的css transform功能极为强大。它提供了类似于jquery的css selector,再配上自定义的操作符,可以让我们极为方便且准确地更新某块html代码中的数据
  4. lift不是mvc结构,而是view-first。在一个html页面中,嵌入了很多小块的snippet,它们在运行时,可以取得业务逻辑数据,通过css transform功能替换掉自己范围内的html代码,形成最终的代码
  5. 另外,lift还有actor、comet等,用来做聊天室之类的程序很方便,不过目前项目还没有此类需求,我也没有机会尝试

可以说lift的这几个特点都是很有特色的,跟我们常用的大多数mvc框架都不一样,甚至某些方面更好相反。学习和使用lift,可以让我们开拓自己的思路:原来不是所有的web框架都是一样的,我们用另一种不同或者相反的方式,也能够一样做好。

从这快一个月的项目经验,我认为lift不是一个容易掌握的框架,而且对于我们常见的大多数类型的网站,都不是一个很好的选择。我认为lift框架适合以下场景:

  1. 安全性要求极高的网站,如银行等。使用lift不需要做任何特别的设置,就已经解决了绝大多数平时可能遇到的安全问题
  2. 聊天室之类的实时展示类网站。lift对这方面的支持非常强大。
  3. 需要ajax局部更新网页,但是不熟悉javascript,或者不想写javascript代码的人
  4. 只想用scala做网站的人(因为scala的web框架选择不多,lift是最成熟的那个)

而其它时候,我们往往有更好的选择:

  1. 传统的多页面网站。市面上大多数的框架都适合做这种,随便找一个的开发效率都要超过lift
  2. 单页程序,且功能比较炫的。选择前端框架(如angularjs)和随便一个能提供json交互接口的后台语言

我们这个项目属于“传统的多页面”网站,使用lift可以实现,但没有发挥出它的优势。这个项目如何使用play1或者ror等框架,可以很轻松的做出来,哪怕中途很多修改,也会比较容易。不过我们之所以使用lift,主要原因是为了尝试scala,而lift作为scala中最成熟的web框架,使用它也算是理所应当了。

这里说一下lift中的做法和优缺点。

  1. 生成form表单

lift中的安全性极高,是因为所有的表单,都是由scala生成的。我们不在html上设计表单,也不写form/input,而是定义一个继承于LiftScreen的类,在里面声明各input,给它写明label、默认值、验证函数等,然后lift在生成html的时候,自动产生相应的html代码。

优点是可以在生成时产生随机的name更加安全,另一点是使用它默认的form样式,可以省掉很多html代码。不过如果想设计一个效果特殊的form表单时,就需要覆盖其toForm方法,在scala代码里写一些html代码,这种方式让人感觉很束手束脚。

  1. View-First模式

跟传统的MVC模式不同,lift是view-first模式,它的意思是,页面是首先被访问的,它是老大。我们写的业务逻辑代码分成一块一块的叫snippet,我们把它们引用在html标签上的某些位置,它们所在的标签的里面的html代码即可被它们访问或修改。

这个感觉非常像一个JSP页面,里面嵌入了一些jsp tag,只不过jsp tag只能向里面的html模板传一些变量,而lift的snippet拥有随意改变其中html代码的功能。

说到优点,这种方式更符合我们的直觉,在view-first的眼里,页面似乎是由一堆积木拼在一起,添加或者减去什么,只需要关注变化的那一小块。而在mvc中,页面上的变化都会影响到controller,因为controller需要添加或者减少相应的数据才能适应view层的变化。当页面中的数据多的时候,controller里到处充斥的混在一起的代码,会让人觉得很难理清头绪。

但在另一种情况,使用mvc又方便一些,比如一些相同的小数据,分散在页面的各处。如果是mvc,直接传一个变量进去即可,而view-first,可能要在多个snippet中分别取一次。

我略倾向于view-first,因为当网站的页面中有很多可重用的小块,使用view-first可以很方便地把它们变成一个个小组件。而使用MVC想做到相同的效果要麻烦很多,除非你的view层也提供了类似snippet这样的功能。

  1. css transform

Lift中的css transform功能十分强大。之前见到的其它框架或者模板引擎,都是向view中提供一些数据,让view自己在合适的地方展示它们。而lift通过css transform,可以让我们对某块html以类似于jquery的方式对它们随意修改。在修改的过程中,我们即可以尽量保持html代码原来的结构和内容,也可以大刀阔斧地修改,实现出完全不同的效果。甚至还可以对产生的html代码再进行新一轮的transform。使用这种方式,我们可以实现非常强大的组件,而只需要定义一些结构不那么严格的html模板,这种能力太神奇了。

但从另一个角度来看,使用css transform,当替换的东西一多时,可读性就不那么好了。我们眼前看到的html代码,很可能跟最终的html完全没有关系,而想知道最终是什么样子,我们只能一句句地读定义的css transform代码,同时在脑海中想像出每一句执行之后的效果,这是一个相当费脑子的事情。同时css transform的代码是字符串,只要里面写错一点,最终的效果可能就跟预想的不同,而要想查出问题,只能一边开着html页面,一边开着css transform页面,然后眼睛在两边一一对比,这种痛苦经历过一次就很难忘了。

另外,lift似乎推荐使用id和class来定位代码,所以当你想修改一句html代码

user name
的时候,你会有一种不敢下手的感觉。因为nickname可能被lift用了,也可能被css用了。除非你小心地查找并确定没有混用的时候,你才敢修改它。

今天看到css transform支持@name,即name属性,所以我们可以写成

..
,这样可以让lift与css隔离开,修改的时候也不会迷茫。会不会好一点?

  1. 使用Scala语言

Lift使用Scala语言,并且利用了它的很多强大的功能,比如隐式转换等,在lift中用得非常多。一方面我们可以让代码写得简单一些,但同时增加了调试与查错的难度,经常发现自己的代码编译不过却又找不到原因。

正是因为Scala语言的强大,xml的内置支持等,才有了lift框架,但同时又因为Scala语言的难度、编译的缓慢、IDE的支持不好,又让我们在使用lift时,经常由于外在原因而很受打击。比如在一个i7/8G/SSD的macbook上,用Idea的Scala插件来写lift程序时,经常卡顿,而使用sbt运行单元测试或者重启jetty时,要等很久的编译时间。如果你的上司经常查看你的进度,问你为什么老是发呆不工作的时候,你会有砸电脑的冲动。

  1. 对Ajax的内置支持以及生成js代码

Lift中提供了一些类,对应js中的相关结构,让我们可以用scala的思路来写代码,而它们会生成正确的js代码在浏览器端执行。在大多数情况下,它们运行得很好并且很简单。但如果某个时候,我们必须实现一些较复杂的js效果,但又不想手写js的时候,利用lift来生成js代码还是比较痛苦的。因为它写出来的代码可读性往往不太好,而且臃肿复杂,所以有时候还不如直接写js来得方便。想通过lift来逃避js的想法往往难以实现,但如果不怕写js代码了,采用前端js框架来做网站,又不必使用lift了。

  1. Lift中处处是坑

Lift中坑很多,非常多。一方面是因为相关的文档和说明很少,很多时候都需要看源代码才知道怎么回事,另一方便lift中有很多隐晦的约定,比如它在生成表单时,会去寻找模板中class为next的input,替换为它生成的submit按钮。这只有看了源代码才知道有这么回事,我们怎么能凭空想到它要去找一个叫next的东西?

我们在写代码的过程中,往往会遇到一些问题,而这些东西早已有了相应的解决方案,只是隐藏在lift的源代码里,没有文档、没有注释,就一个方法或者几行代码。我们只有读了它的源代码,并且推出了那些代码的作用,才知道该怎么去使用。

我怀疑这是lift的作者故意这么做的,因为lift本身就是一个比较高端的框架,对使用者的要求很高。如果一个使用者没有阅读源代码的习惯和能力,也许就不应该成为lift的用户。

我目前所感受到的东西都差不多写在这里了。Lift是一个很有特色的框架,但我想我不会在自己的项目中使用它。因为我很少会遇到lift最适合的那种类型的网站。如果是普通的多页面网站,我用play1搞定,如果是单页面网站,我会用angularjs来做,这两种都会比lift的开发效率高很多。

一些评论

guxiangguo

但在另一种情况,使用mvc又方便一些,比如一些相同的小数据,分散在页面的各处。如果是mvc,直接传一个变量进去即可,而view-first,可能要在多个snippet中分别取一次。
=> 可以用Menu.param只取一次

Lift是一个很有特色的框架,但我想我不会在自己的项目中使用它。
=》恰恰相反,研究源代码是一种乐趣,自己的项目第一选择Lift。

coolwasp

年初,听从作者的建议,在用play1写一个网站,感觉就像在写php代码,比其他框架使用起来方便多了,我们模板是集成japid,前端kissy+jquery,感觉还不错。

comments powered by Disqus