模板是否应该支持函数调用?

首先,将Java中的Method分成:Subroutine和Function两种,
按照“契约式设计原则”的说法,Subroutine是有副作用的(side-effect),而Function是没有副作用,
语法上,Subroutine通常没有返回值,即void方法,而Function则有返回值,
比较明确的是,模板肯定不允许调用Subroutine,否则肯定会引入大量业务逻辑,

现在待讨论的是,模板中是否允许调用Function?
如:
${object.funtion(arg1, arg2)}
衍生出的还有静态Function:
${funtion(arg1, arg2)}

在CommonTemplate([url]http://www.commontemplate.org[/url])设计之初,
是禁止调用Function的,因为Function会使模板复杂化,通常可以用其它更好的方式表达:
1.无参的Function,可以直接去掉括号,简化成属性方式,如:
String.trim
String.toUpperCase
List.size
Number.toString
等等
2.有参的Function,也可用其它更形象化的操作符处理,如:
用Map[key]代替Map.get(key)
用List[2..4]代替List.subList(2, 4),
将String看作char[]数组,用String[2..4]代替String.substring(2, 4),用String[2]代替String.charAt(2),
用"aa" ~= "AA"(约等于) 代替 "aa".equalsIgnoreCase("AA")
等等

通常处理的Domian对象,都是POJO,基本数据类型,集合类等,
如果标准包对这些都支持的比较好,那禁掉Function看起来是可行的。

然而,标准包不可能想到用户所有的需求,
所以必需留给用户容易实现的扩展点,

以最近版本加入的orderby为例,
假设其不在标准包,而是用户自己扩展实现的,
需求定义:
实现集合类的按属性排序,如:
$for{book : books}
其中,books是一个包含Book的集合,Book是一个POJO,有title, price等属性
现需要在循环之前对books按价格排序,当然可能是升序或者降序,也可能是多个属性,

有三种方案可以实现:
1.扩展静态方法:
$for{book : orderby(books, "price")}
JSP2.0的EL和Velocity就是用的类似此方案
2.扩展对象方法:
$for{book : books.orderby("price")}
3.扩展二元操作符:
$for{book : books orderby "price"}

如果禁止方法调用,当然也应禁止静态方法,
那就只能用第三种,操作符扩展,
但如果这种需求很多,会不会使操作符的数量骤增,
表达式的可读性及易用性都会降低,

看起来,第二种方案比较合理,通过在外部给集合类扩展一个方法,
但就因为这,开启Function调用,是否应该?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值