2006年10月26日星期四

JSP,Velocity,Jelly and Ruby

项目中要动态产生文档,开始用JSP做了个简单原型,后来觉得代码比较混乱,换上了Velocity:一种模板语言。 虽然大同小异,但有些地方还是很方便。比如原来jsp中:
<%=person.getPostion()%>
现在只要$person.position就可以了,少了很多讨厌的百分号。还可以定义function,以及其他一些你能想到的特性。很有点脚本语言的味 道,有如prototype.js的$(),更符合编程思路,大家都喜欢,觉得这样才自然(prototype这里大概从ruby中汲取了灵感)。
还有另外一个类是的库jellyXML-based scripting and processing engine。使用了一种XML和${}的混和语法。比如:

<j:forEach items="${IMPORTS}" var="i" trim="false">
import ${i};</j:forEach>

而velocity则较为一致:

#macro( getBox $thisboxvalue $boxvalue )
#if ( $thisboxvalue == $boxvalue ) a #else b #end
#end

单从语法上讲,jelly类似jsp + jstl。While Jelly has found some success in projects such as Maven, the general consensus is that XML is a poor choice for a programming language even the creator of Jelly apologized at http://radio.weblogs.com/0112098/2004/03/26.html#a472.
其实ANT用XML作语言也有同样的问题。TheServerSide上有篇文章Allen Holub: Just Say No to XML 说明了这一点。 那为什么jsp不做成这样子呢?连rails也是这种讨厌的风格?(还好ruby的语法很方便)个人认为一则效率的考虑:velocity大概有个预先装入、解析、预编译的过程(待考证),还会将结果放在cache中。二则(更主要)多了一种语法,造成复杂和重复。
velocity还有些设计上的亮点:使用中遇到一种情况,从bean中取出属性后要作个代码页转换然后在页面上显示。由于原来bean的getXXX方 法都已经产生好,手工改费力不讨好。这时参考velocity文档时发现有一个get()的方法:当对于属性A,bean不存在getA()方法时,调用 bean的该方法。nice! 让人想到了ruby也有类似设计:Object有个method_missing的方法.也是很好的idea,方法简单但是效果很好。(参考我的blog:Ruby的method的动态特性
从脚本语言看,Groovy之类从语法上更为强大,也更复杂。如果Java有成熟的、广泛接受的脚本语言技术,velocity大概也无立足之地了。
另: Roller Weblogger的模板也是用了Velocity技术。

2006年10月20日星期五

小试Rails RJS

    RJS是Rails1.1的一个ajax的功能点。这里是一个简单明了的turturail。
    这个framework引入了一个rjs类型的文件,当control的function执行后,同名的rjs文件会被执行来动态产生出(或者说是被翻译为)javascript文件。
    rjs可以为如下的形式:
a = "fkp"
page.insert_html :bottom, 'list',
                 content_tag("li", "Fox2")
page.visual_effect :highlight, 'list', :duration => 3
page.replace_html 'header',
                  a + "b"
利用工具(for example:charles)可以得到其产生的response为:
try {
new Insertion.Bottom("list", "<li>Fox2</li>");
new Effect.Highlight("list",{duration:3});
Element.update("header2", "fkpb");
} catch (e) ......
    让人惊奇!我原来以为返回的是xml形式的(ajax必须返回xml吗?)。
    这样的做法产生一个问题就是js的代码量可能过大,当然这里是因为直接调用而显得很简短(application.js就可以放自定义的js function的地方)。这些js基本上是没有变化的,那么能不能直接传参数呢?这样产生出来的js可以cache(google web tools好像是这样做的)。而rjs的做法感觉是对于page.methodxx的返回值每次来个字符串的相加?
    rjs不仅提供了ruby语法的api来简化js的开发,更重要的是将ajax从view曾剥离出来,而且可以访问server端同名function的导出变量(@开头的?这湮没了xml在B/S间的传递)。
    跟其它的ajax框架不一样(大多可以用js直接访问后台的java function),这种方式去掉了访问的接口的定义(method的返回值没有定义),灵活性更强,因为view可能改变频繁。
    用这种模式后,契约存在两个地方:1)rjs和html。rjs用id来对html element控制,一般的ajax模式是把js和html混合写,由于id粒度过低,分开加大了耦合度;2)ruby和rjs之间的context。显然,google web tools解决了这些问题,但是需要讨厌的compile的过程。
    如果用java来实现,rjs模板可以用java写,也可以为脚本语言(jdk6有更好的支持),而主要不同可能是java代码和模板之间的contex的共享:java可能没有ruby实现的优雅。
    模板产生出来的javascriptbroswer端用如下的形式引用:
<script src="/javascripts/prototype.js?1159875410" type="text/javascript"></script>
<script src="/javascripts/effects.js?1159875410" type="text/javascript"></script>
还不知这些number是做何用处。

2006年10月19日星期四

XUL中的UI重用

XUL是Mozilla的界面描述语言,用来解决跨平台的问题。
XUL的Overlays特性令人感兴趣,其描述为:
Overlays are XUL files used to describe extra content for the UI. They are a general mechanism for adding UI for additional components, overriding small pieces of a XUL file without having to resupply the whole UI, and reusing particular pieces of the UI.
有点类似OO中的继承和方法重写。
一般来说,页面级的重用是比较困难的。JSF(组件级的重用)或者jsp tag只是重用了页面的一部分,开发起来也是费周折。