`
javatar
  • 浏览: 1701089 次
  • 性别: Icon_minigender_1
  • 来自: 杭州699号
社区版块
存档分类
最新评论

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

    博客分类:
  • HTTL
阅读更多
首先,将Java中的Method分成:Subroutine和Function两种,
按照“契约式设计原则”的说法,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调用,是否应该?
分享到:
评论
11 楼 javatar 2007-11-28  
实现函数功能时,
发现一个有趣的事情:函数就是非符号(与变量名同规则)的一元操作符,
如:定义一个非符号一元操作符:abs (取绝对值操作),
则其写法应为:
${abs -1},
但这样,abs和变量名引起歧义,会把abs当成变量,然后减1。
所以应写成:
${abs(-1)}
用括号加强优先级。
这样,也就变成了函数的风格。

当然也能在复杂情况使用:
${2 + abs(abs(-1) - 3)}

基于此,如果配置:
functionAvailable=false
将禁止非符号的一元操作符。
10 楼 javatar 2007-11-27  
leadyu 写道

而且视图层又没参与持久化,哪来只读可写之分

以Webwork或Struts2的Action为例,通常用setXXX表示Form传入数据,用getXXX表示页面展示数据,难道强迫用户getter和setter写全?那样契约性会变差(无法表示这个Action需要什么参数,呈现什么数据),而且不必要的setter可能造成安全问题,如订单额只读,而不能setter等。

leadyu 写道

i m sorry ,why dont you follow JavaBeans Specification?why? 活该!


用户会反过来,我不用这个工具了,这点事都处理不了,你活该,呵呵

9 楼 leadyu 2007-11-25  
其实,我觉得jindow的想法蛮好,你可以把策略这层抽象出来,
类似JDK里面reflect里面的PrivilegeControl,在所有方法调用前拦截。

我只是提出这个策略干脆就以javaBean规范为准算了,毕竟广为接受,同时能够很好的规避业务方法。

当然,bean.size,map.key,这些可以例外,至于你说的问题,你想想有没更好的策略了。只是单纯get*个人认为是不合适的。

至于只读属性,我只能说 i m sorry ,why dont you follow JavaBeans Specification?why? 活该!

而且视图层又没参与持久化,哪来只读可写之分,呵呵。当然你可以想想这个策略。
8 楼 javatar 2007-11-24  
leadyu 写道

不是Object.get*都行,必须有对应的set*,才允许调,单纯的get*,很多都是业务性质的函数,比如查询方法。^_^


那如果是只读属性呢?
7 楼 javatar 2007-11-24  
递归可以考虑用lambda表达式的不动点算子实现

lambda表达式:
http://javatar.iteye.com/blog/137037
6 楼 bigpanda 2007-11-23  
要是不允许函数调用怎么处理递归数据呢?
5 楼 leadyu 2007-11-23  

不是Object.get*都行,必须有对应的set*,才允许调,单纯的get*,很多都是业务性质的函数,比如查询方法。^_^
4 楼 javatar 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

默认禁止,如果实在需要,可自行开启。

算是中庸的解决办法。
3 楼 leadyu 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才允许调用。


2 楼 wl95421 2007-11-22  
不应该
各有各的职责
职责明确,单一才是最重要的
1 楼 jindw 2007-11-21  
我感觉只要有个方法调用的许可策略就可以了。
调用方法前,现判断一下,这个方法能不能允许调用,比如,集合类的只读方法,允许访问。
一些静态的工具方法,如字符处理,允许访问。

直接调用方法,模板语法更加简单。当能,map.key这类大家已经普片接受的规则除外。

相关推荐

    所有函数调用顺序以及函数耗时的Android库

    5. 报告模板:库可能自动生成函数调用图或日志,显示函数调用的顺序和耗时,方便开发者分析。 使用这样的库,开发者可以在不修改应用程序核心代码的情况下,轻松获取关于函数调用和性能的数据。这对于大型项目或者...

    NC65按钮调用模板.rar

    "NC按钮调用模板"则表明这个模板是针对按钮操作的,很可能涉及按钮触发的函数调用或者事件响应。这可能意味着模板包含了对不同事件(如点击、悬停、长按等)的预定义处理,使得开发者可以方便地根据需要进行绑定。 ...

    微信小程序Page中data数据操作和函数调用方法

    在微信小程序的开发过程中,Page()函数起到了注册页面的作用,它接受一个对象作为参数,用于指定页面的初始数据、生命周期函数、事件处理函数等,而页面的数据操作和函数调用是小程序开发中非常重要的部分。...

    JTBC函数调用补充

    在本文中,我们将深入探讨JTBC函数调用的一些核心概念,特别是与首页模板和栏目列表模板相关的调用代码。 首先,我们来看首页模板调用代码。`{$=itransfer('top', '1', 'topx=10;tnum=30;genre=article;class=1')}`...

    重载函数模板与非模板函数示例

    值得注意的是,尽管这个函数没有使用模板关键字`template`,但它仍然可以与模板函数一起工作,并且在调用时根据参数类型自动选择最合适的版本。 #### 主函数调用分析 在`main`函数中,通过几个具体的调用来演示...

    ABAP调用函数自动填充模式

    `Z_SDN_PATTERN_FUNC_START`可能是另一个与自动填充模式相关的代码片段或示例,可能是用来启动函数调用的模板或模式。这种模式可能包含了一些预定义的结构,使得开发人员能够快速地开始函数调用,而无需从头开始编写...

    C++函数重载•函数模板•类模板.doc

    函数模板是C++中的一个强大特性,它可以用来创建一个通用功能的函数,以支持多种不同形参。函数模板的声明方法是: template标识符> 函数声明 例如: template T abs(T x) { return x < 0 ? -x : x; } 在上面的...

    模板-函数模板与类模板.ppt

    - 调用函数模板时,编译器会根据传入的实际参数类型推断出模板参数的类型,然后生成对应的实例化函数。 2. **类模板**: - 类模板类似于函数模板,但应用于类。它允许用户声明一个类的模板,其中某些数据成员、...

    c++函数模板和类模板计实验报告

    在主函数`main`中,我们分别对整型和双精度浮点型数组调用了`sort`函数,展示了函数模板的实例化过程,即编译器根据实际参数类型自动生成相应的函数版本。 第三部分涉及了函数模板的显式实例化和隐式实例化。在示例...

    c调用C++函数

    由于C++支持名称空间和类,而C语言没有这些概念,因此直接在C代码中调用C++函数会遇到兼容性问题。 为了使C代码能够调用C++函数,我们需要遵循以下步骤: 1. **extern "C" 声明**:C++允许使用`extern "C"`来告诉...

    函数的定义和调用

    接下来,我们讨论**函数调用**。在程序的其他地方,你可以通过函数名和传递实际参数来调用已定义的函数。调用格式如下: ```cpp 返回值 变量名 = 函数名(实际参数, 实际参数, ...); ``` 实际参数的值会赋给形参,...

    函数模板与类模板.docx

    例如,在下面的代码中,如果我们使用自动类型推导来调用函数模板mySwap,但是参数类型不同,编译器将报错: ```cpp void test01() { int a = 10; int b = 20; char c = 'c'; mySwap(a, b); // 正确 mySwap(a, ...

    C++ 通过字符串调用函数

    要将字符串转换为函数调用,你需要先创建一个函数指针类型的映射表,然后将函数名作为键,对应的函数指针作为值。这样,你可以通过查找字符串来获取对应的函数指针并执行它。 ```cpp #include #include #include ...

    函数直接调用几种方法_loki_grandmotherxmb_函数直接调用_元编程_

    如果这个函数调用方法支持MFC,那么它可以在MFC环境下无缝集成,方便开发基于Windows的应用程序。 至于"grandmotherxmb",由于没有更多的上下文,我们只能推测它可能是代码示例的作者或者某个特定功能的标识符。...

    python调用C++函数

    然而,由于C++函数可能会涉及对象、模板和命名空间,因此直接使用`ctypes`并不总是可行的。在这种情况下,我们可以采用以下几种方法: 1. **Cython**: Cython是一种Python的超集,它能够编译成C扩展模块,从而可以...

    函数模板sort<T>,

    用函数模板方式设计一个函数模板sort,采用直接插入排序方式对数据进行 排序,并对整数序列和字符序列进行排序

    函数调用扩展_函数扩展_raysfrs_函数入口地址_functor_虚函数_

    在编程领域,函数是执行特定任务的代码块,而函数调用是程序中执行这些任务的方式。本篇文章将深入探讨几种函数调用扩展方法,包括使用函数入口地址、函数对象(functor)以及虚函数,以实现更灵活的代码设计。 ...

    Wordpress调用函数大全

    在本文中,我们将对 WordPress 中的一些常用的函数调用方法进行汇总,旨在帮助大家更好地掌握 WordPress 函数调用知识。 WordPress 模板基本文件 在 WordPress 中,模板基本文件是非常重要的,它们决定了 ...

Global site tag (gtag.js) - Google Analytics