锁定老帖子 主题:模板是否应该支持函数调用?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-11-21
按照“契约式设计原则”的说法,Subroutine是有副作用的(side-effect),而Function是没有副作用, 语法上,Subroutine通常没有返回值,即void方法,而Function则有返回值, 比较明确的是,模板肯定不允许调用Subroutine,否则肯定会引入大量业务逻辑, 现在待讨论的是,模板中是否允许调用Function? 如: ${object.funtion(arg1, arg2)} 衍生出的还有静态Function: ${funtion(arg1, arg2)} 在CommonTemplate(http://www.commontemplate.org)设计之初, 是禁止调用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调用,是否应该? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-11-21
我感觉只要有个方法调用的许可策略就可以了。
调用方法前,现判断一下,这个方法能不能允许调用,比如,集合类的只读方法,允许访问。
一些静态的工具方法,如字符处理,允许访问。
直接调用方法,模板语法更加简单。当能,map.key这类大家已经普片接受的规则除外。
|
|
返回顶楼 | |
发表时间:2007-11-22
不应该
各有各的职责 职责明确,单一才是最重要的 |
|
返回顶楼 | |
发表时间:2007-11-22
符合javaBean规范的function调用要支持。
比如: $set a=BussinessService1.***() $if{a=='1'} ... $else ... $end 这样写模版是evil的。这样把模型层的业务代入了视图,MVC中的M无法重用。而 $if(formBean.tag=='1') ... $else ... $end 这样是合理的,更优于完全屏蔽function调用 这样的控制比在模型层把tag计算出来,set到Context中更有效,更具有封装性,否则模型层的计算就成了一堆散列的参数计算,非常零乱。 也就说,建议,对符合javaBean规范的function调用支持,比如formBean.tag,就必须有getTag,和setTag才允许调用。 |
|
返回顶楼 | |
发表时间:2007-11-23
leadyu 写道 符合javaBean规范的function调用要支持。 ... 也就说,建议,对符合javaBean规范的function调用支持,比如formBean.tag,就必须有getTag,和setTag才允许调用 这个肯定是支持的,bean.getProperty()和bean.isProperty()都可以用bean.property调用, 非符合Bean规范的部分也支持(因为JDK中不是所有取值函都支持Bean规范),如:String.trim,List.size等 jindw 写道 我感觉只要有个方法调用的许可策略就可以了 这个想法不错,规则可定义比较好, 如,可定义许可: Object.get*, Object.is*, String.trim, List.Size 而像remove等禁止。 (注:List的remove方法违反契约式设计原则,它不是无副作用的函数,但却有返回值) 现在,模板引擎把bean.function(arg1, arg2)的语法解析已经实现了, 只是在配置中,加了一项: functionAailable=false 默认禁止,如果实在需要,可自行开启。 算是中庸的解决办法。 |
|
返回顶楼 | |
发表时间:2007-11-23
不是Object.get*都行,必须有对应的set*,才允许调,单纯的get*,很多都是业务性质的函数,比如查询方法。^_^ |
|
返回顶楼 | |
发表时间:2007-11-23
要是不允许函数调用怎么处理递归数据呢?
|
|
返回顶楼 | |
发表时间:2007-11-24
|
|
返回顶楼 | |
发表时间:2007-11-24
leadyu 写道 不是Object.get*都行,必须有对应的set*,才允许调,单纯的get*,很多都是业务性质的函数,比如查询方法。^_^ 那如果是只读属性呢? |
|
返回顶楼 | |
发表时间:2007-11-25
其实,我觉得jindow的想法蛮好,你可以把策略这层抽象出来,
类似JDK里面reflect里面的PrivilegeControl,在所有方法调用前拦截。 我只是提出这个策略干脆就以javaBean规范为准算了,毕竟广为接受,同时能够很好的规避业务方法。 当然,bean.size,map.key,这些可以例外,至于你说的问题,你想想有没更好的策略了。只是单纯get*个人认为是不合适的。 至于只读属性,我只能说 i m sorry ,why dont you follow JavaBeans Specification?why? 活该! ![]() ![]() 而且视图层又没参与持久化,哪来只读可写之分,呵呵。当然你可以想想这个策略。 |
|
返回顶楼 | |