论坛首页 Java企业应用论坛

论面向组合子程序设计方法 之 微步毂纹生

浏览 87458 次
该帖已经被评为精华帖
作者 正文
   发表时间:2006-01-05  
夏日的猫 写道
ajoo 写道

其实,我用jaskell写了一个规则语言出来的。(不过,我看drools的例子,似乎不懂编程的人也玩不转阿)


jaskell我看了一下,更像是bsh之类的脚本语言,不大像是规则语言啊。


xml也不是一个规则语言阿。:-)
例子代码:
woman_day_discount = and[
  eq(3, month);,
  eq(8, day);,
  eq("female", gender);
].then(discount 0.05);;

我琢磨着培训培训没准儿也成。

夏日的猫 写道

ajoo 写道

不过,我看drools的例子,似乎不懂编程的人也玩不转阿


那个当然要培训了。不过想对于wfmc和其它script语言来说,我觉得已经是很简单的东西了。


反正看见drools的那个<parameter>居然要写class的全名,还要弄好多xml namespace,就觉得不是那么对终端用户友好。
0 请登录后投票
   发表时间:2006-01-05  
firebody 写道

对不起,我也觉得你想当然了。我不知道你有没有看过Functor?
说出“连0步“都不能达到,我更觉得你武断。更想当然。

http://www-128.ibm.com/developerworks/cn/java/j-fp/

我当然看过了。我说他不成,两点原因:
1。java里面玩fp我玩的多了。这个functor那点东西实在小儿科。我的jaskell能做的比他多多了。我都没说jaskell可以做这个规则引擎。它那个打折的例子太简单化了,都没有一个rule是否applicable的判断。这种东西直接用annonymous class做就得了,还简单清楚的多。用functor整个自己找罪受嘛。

2。我是实际做了这个简易rule engine的,我自己当然知道哪里是关键(针对Rule接口语义的组合,而不是一般意义上的函数组合),哪里是“10步都不到”。

你要是真对自己说的话负责的,就真正用functor做一个同等功能甚至更强的rule engine出来。那时候再说别人比你“更”想当然才有说服力,而不是象不过大脑的气话。
0 请登录后投票
   发表时间:2006-01-05  
夏日的猫 写道


ajoo在这里的例子的确就是一个最simple的规则引擎。如果从规则引擎的角度衡量它,那么这个规则引擎没有推理引擎,也还没有抽象出规则语言,或者说它使用java class作为默认的规则语言,因此它的实施起来是很困难的。(规则语言一般是提供给客户或者实施人员使用的,让他们自己定制规则。很难想象让客户写java class)。

如果说从这个案例来理解co,我感觉从折扣策略业务系统-&gt;规则引擎业务系统这个分析过程就是co的过程。如果下一步老板还要求把程序员炒鱿鱼后还能自己改规则,不知道ajoo是不是就能co个规则语言出来了。 不知道这种理解对不对,还请各位大牛指点阿。

恰恰相反,我觉得规则引擎通常都能和业务系统结合的很好,可以直接从RuleContext中获得domain object(参考JSR-94),只是需要客户掌握规则语言。不过大部分规则语言的语法都模仿自然语言,所以很好掌握。

不过就这个例子来说,我觉得还是应该直接采用规则引擎比较好,能够拿来的,干嘛要自己开发呢?


无论是什么规则引擎,想要把规则语言直接给客户使用都是不切实际的空想,越是强大灵活的规则语言就越难掌握,学习成本越高,客户的抵触情绪也越高。对于特定业务领域而言,业务规则总是表现出一定的行业规律,只要针对这些特定规律编写出简单可行的规则引擎即可,对于客户来说,提供一个有针对性的GUI配置界面甚至比规则引擎本身更具吸引力。以通用规则引擎去套特定业务,实际上会更别扭,自行开发会反而更划算,当然,前提是要有这个实力。
0 请登录后投票
   发表时间:2006-01-05  
ajoo 写道
firebody 写道

对不起,我也觉得你想当然了。我不知道你有没有看过Functor?
说出“连0步“都不能达到,我更觉得你武断。更想当然。

http://www-128.ibm.com/developerworks/cn/java/j-fp/

我当然看过了。我说他不成,两点原因:
1。java里面玩fp我玩的多了。这个functor那点东西实在小儿科。我的jaskell能做的比他多多了。我都没说jaskell可以做这个规则引擎。它那个打折的例子太简单化了,都没有一个rule是否applicable的判断。这种东西直接用annonymous class做就得了,还简单清楚的多。用functor整个自己找罪受嘛。

2。我是实际做了这个简易rule engine的,我自己当然知道哪里是关键(针对Rule接口语义的组合,而不是一般意义上的函数组合),哪里是“10步都不到”。

你要是真对自己说的话负责的,就真正用functor做一个同等功能甚至更强的rule engine出来。那时候再说别人比你“更”想当然才有说服力,而不是象不过大脑的气话。

好的,既然你这样说了。 我就试试用Functor实现age0的需求,不过这两天我没空,等到周末再贴出我的代码,赫赫。
(BTW:火尸很久没吃猪了)  
0 请登录后投票
   发表时间:2006-01-06  
为什么我说apache的functor没用呢?

首先,它仅仅提供的是fp里面最最基本的一些函数组合,flip, const, curry。更高级的monadic组合子它提都没提。这些东西如果不是语言直接支持, 通过提供一个库来实现的价值并不大,比如那个例子中的:
BinaryPredicateUnaryPredicate moreThanUSD100 = new BinaryPredicateUnaryPredicate
	  (new UnaryCompositeBinaryPredicate(new IsGreaterThanOrEqual();, getItemPrice, usd100););;

用jaskell表示,不过是:
moreThanUSD100(arg); = getItemPrice(arg); >= 100;

拽一点,省略掉这个arg参数,也不过是:
lift2 bin f1 f2 arg = bin(f1 arg, f2 arg);;
moreThanUSD100 = lift2((>=);, getItemPrice, const 100);;

我不需要依赖一个库, 代码也比apache functor直接简单的多。

其次,apache functor的组合,一样要面临java中勉强使用fp的问题:代码不容易懂,调试和错误定位困难。fp的好处没见到,代价倒是付了个十足十。


最后,也就是最重要的问题:那个老印的直接用functor解决业务问题的例子,强迫业务逻辑接口只能是一个参数,一个返回值的函数。这个假设很多情况下不成立。———— 即使是纯函数式的haskell的monad也是不局限于单函数的。一个实现Monad的数据类型可以有任意多个method。

Rule就不是简简单单的一个函数,它有它的先决条件的。一个rule如果先决条件不满足,根本就不会执行。
一个针对美女的折扣规则,如果面对关西大汉,什么值也不应该返回,而应该是n/a。(返回0或者null之类的特殊值都有局限性)

还有,随着需求的复杂,我们也许还需要支持"getCondition()"这个方法来取得一个rule的先决条件,此时,一个单函数的假设就更不成立了。

co,co,借鉴的是fp的组合子思想,而不是简单地邯郸学步弄几个高阶函数组合就算完事。
0 请登录后投票
   发表时间:2006-01-06  
觉得有没有推理引擎才是rule engine和基于组合子的rulet(我起的名字)的区别。

老庄说的不错,规则引擎和prolog这类logical programming还是很象的。

每个rule都可能影响fact集合,从而自动引发其它的规则,这种自动推理能力才是规则引擎的与众不同之处。

而age0给的则是一个简单得多的场景。我们只需要在已知的一些数据基础上做一些预先定好的的业务决策。这些业务决策逻辑可能很复杂变态,所以co的组合可以派上用场,但是它们都不需要推理功能。

总结一下:
1。业务逻辑相对比较简单,但是需要自动推理功能的,用规则引擎。
2。业务逻辑复杂,if,else, and, or一大堆的时候,如果不需要自动推理,则用rulet。
0 请登录后投票
   发表时间:2006-01-06  
ajoo 写道
为什么我说apache的functor没用呢?

首先,它仅仅提供的是fp里面最最基本的一些函数组合,flip, const, curry。更高级的monadic组合子它提都没提。这些东西如果不是语言直接支持, 通过提供一个库来实现的价值并不大,比如那个例子中的:
BinaryPredicateUnaryPredicate moreThanUSD100 = new BinaryPredicateUnaryPredicate
	  (new UnaryCompositeBinaryPredicate(new IsGreaterThanOrEqual();, getItemPrice, usd100););;

用jaskell表示,不过是:
moreThanUSD100(arg); = getItemPrice(arg); >= 100;

拽一点,省略掉这个arg参数,也不过是:
lift2 bin f1 f2 arg = bin(f1 arg, f2 arg);;
moreThanUSD100 = lift2((>=);, getItemPrice, const 100);;

我不需要依赖一个库, 代码也比apache functor直接简单的多。

其次,apache functor的组合,一样要面临java中勉强使用fp的问题:代码不容易懂,调试和错误定位困难。fp的好处没见到,代价倒是付了个十足十。


最后,也就是最重要的问题:那个老印的直接用functor解决业务问题的例子,强迫业务逻辑接口只能是一个参数,一个返回值的函数。这个假设很多情况下不成立。———— 即使是纯函数式的haskell的monad也是不局限于单函数的。一个实现Monad的数据类型可以有任意多个method。

Rule就不是简简单单的一个函数,它有它的先决条件的。一个rule如果先决条件不满足,根本就不会执行。
一个针对美女的折扣规则,如果面对关西大汉,什么值也不应该返回,而应该是n/a。(返回0或者null之类的特殊值都有局限性)

还有,随着需求的复杂,我们也许还需要支持"getCondition()"这个方法来取得一个rule的先决条件,此时,一个单函数的假设就更不成立了。

co,co,借鉴的是fp的组合子思想,而不是简单地邯郸学步弄几个高阶函数组合就算完事。

考虑到整合先有的领域模型,同时考虑更复杂的需要。我觉得两者之间的代码两不会差别太多。只不过Functor的组合函数,写起来看起来确实不好。没有脚本解析那么好看,不过它也带来更灵活定制的优势,比如*,/,假设我需要特定scale的精度,那么jaskell不知道需要怎么才能实现,ajoo你说说看。 如果用functor,只需要重新定义Multply即可。
我对于Functor的观点是:不是全部的函数编程,但是体现了最精华的部分,失去了脚本式解析的优势,但是带来更容易整合,灵活的优势。
你可以看看它给出的example
0 请登录后投票
   发表时间:2006-01-06  
脚本解析并不是functor的本质缺陷,它的本质缺陷是:组合的只是简单函数,而不是任意接口。


不管是用脚本,还是java,如果没有一套针对具体Rule接口的组合规则,仅仅靠一般的函数组合,都是徒劳的。
即使用jaskell也不足以作出一个可用的rule engine。所以这根本不是一个脚本解析器的问题。什么重载函数之类的都没在点子上。(当然,限制精度这种东西是小case了,你只要在java里面把这个限制精度的乘法函数实现出来,然后输入到jaskell里面,假设叫mul,那么就用这个mul函数代替*好了)

functor那点东西也远远不是什么“函数编程的精华”。你太小瞧函数编程了。
哎,买椟还珠啊。
0 请登录后投票
   发表时间:2006-01-06  
ajoo 写道
脚本解析并不是functor的本质缺陷,它的本质缺陷是:组合的只是简单函数,而不是任意接口。


不管是用脚本,还是java,如果没有一套针对具体Rule接口的组合规则,仅仅靠一般的函数组合,都是徒劳的。
即使用jaskell也不足以作出一个可用的rule engine。所以这根本不是一个脚本解析器的问题。什么重载函数之类的都没在点子上。(当然,限制精度这种东西是小case了,你只要在java里面把这个限制精度的乘法函数实现出来,然后输入到jaskell里面,假设叫mul,那么就用这个mul函数代替*好了)

functor那点东西也远远不是什么“函数编程的精华”。你太小瞧函数编程了。
哎,买椟还珠啊。

[****删除不雅词汇(庄表伟)]别转移话题阿,专业的规则引擎俺们先不讨论,我们做的类似ToolKit的之类的也没法跟他们成熟的框架相比,现在我们讨论的是基于age0提出的需求,用Functor或者你的Jaskell搭出来,看谁的更容易扩展,更简洁。
至于那些Rete,JSR** ,以后再讨论。
0 请登录后投票
   发表时间:2006-01-06  
哎。我说跟Rete之类的有关了么?

就age0这个需求,用jaskell还是用functor都是扯淡。你要不针对rule语义作组合,死抱着apache functor就没意义。或者说apache functor对这个问题没有任何价值。jaskell对这个问题有一定价值,但是也就起一个语法封装的作用,真正的核心还得是用java对Rule接口作组合。

算了,不说了。你还是自己动手做做吧。空对空没意思。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics