锁定老帖子 主题:论面向组合子程序设计方法 之 微步毂纹生
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-08-09
把某些子程序看成终结符,另一些看成非终结符,然后开始画状态图,然后矩阵,然后矩阵化简?
|
|
返回顶楼 | |
发表时间:2005-08-09
ajoo 写道 可是oz,oo的gof的模式,也是主观的很啊。对同一个问题,有人觉得应该visitor,有人觉得应该factory,一样没有一个可以依赖的原则呀。
gof确实给出了一些场景,总结了很多东西,这也是他们能够出书,而我们只能随便经验性的谈论的区别。 对co,我觉得也是有一些模糊的规律可循的。可惜,这种作总结的工作我不擅长。也许象martin fowler这样的人才合适。 不过,我倒是觉得,oo里面提出的那些原则:正交,单一职责,重构,都是可以原封不动地挪到co里面的。程序开发是有些共性存在的,这并不是oo的专利。 哈哈,正是因为很主观,所以才需要总结,而且也可以总结出来。 其实我觉得co的好处恰恰不是如你所说,是表现在简单场景下的灵活变化,而是在复杂场景下的简单变化中。特别是当你的combinator可以在某些粒度下设置的够好的时候,就可以使用简单的组合原则,来适应多变的复杂场景。而组合在我看来更容易被动态的实现,至少比分解能更容易。 |
|
返回顶楼 | |
发表时间:2005-08-09
引用 简单场景下的灵活变化,而是在复杂场景下的简单变化中
能不能对这两者分别举个例子?我想保证我们说的是一件事。 |
|
返回顶楼 | |
发表时间:2005-08-09
我并没有意思要批评什么,现在时间也比较紧张,其实其他人都已经提出来了,我感觉他们(提问题)水平都比我高,希望不要有什么成见。
|
|
返回顶楼 | |
发表时间:2005-08-09
在任何一个系统当中CO和OO基本上都是并存的,CO主要是集中在通用工具集合这一范畴,而OO则主要集中在规范、协议这一类的高级抽象范畴,各司其职,河水不犯井水。前一段时间曾经研究过纯CO的可行性,但是没有获得成功,唯一的收获就是对OO的认识更加深入,对OO的信心更加坚定。
|
|
返回顶楼 | |
发表时间:2005-08-09
ajoo 写道 引用 比如,现在有个需求,当logger级别超过一个值的时候必须写到Logger文件中,否则只需要输出到控制台即可;或者是某个级别的log需要单独输出到一个独立的log文件中;
现在你现有的是不够的,必须增加,但是这些需求是你一开始不能料到的 真的? 看着: Logger log_to_file = writer(some_file_writer);; Logger console_log = writer(new PrintWriter(System.err););; Logger mylogger1 = ignore(some_level, log_to_file, console_log);; Logger log_to_special_file = writer(special_file_writer);; Logger common_logger = ...; Logger mylogger2 = filter(some_level, log_to_special_file, common_logger);; 哈哈,正是给我提供素材呢。小样儿,co要是连你这么点小case都对付不了,还更得了呢。 你说我拿着锤子找钉子好说,你说你没事拿钉子找锤子这不是找不舒服么? 不过谢谢你,回头我把这个例子加进去,也正好说明co的强大。(你愿意叫这个东西decorator,随你便,反正如果能更方便你理解,也就行了。对了,decorator和普通多态有什么区别?为什么叫decorator?) ok,栽乐,看来随便想的东西不行,对于LOG这件事,似乎没有更多的特殊情况乐,即使有,如:当Log文件达到某个长度(比如5M)就刷新整个LOG文件(等于重新来过,旧LOG不要乐);其实也没什么特别的意义,你增加组合子就基本OK。 那么我的另个问题是,你怎么来控制组合子的设计,以保证不会过度?因为一开始你如果只从细节上去考虑,可能会做很多的组合子以便将来应付变化,但是也许根本没有什么变化呢?比如,也许我要的LOG系统只是需要根据level能将需要的level输出到控制台就可以乐,其它什么写文件之类的根本不需要(让server来帮我们做这些事情)。这个时候会不会有点过? 顺带问的是:一个单表增删改的实现上,你会怎么发挥它的威力呢? |
|
返回顶楼 | |
发表时间:2005-08-09
ajoo 写道 那么怎么处理:“如果level>=x写入文件1,同时在屏幕上打印(不过不打印stack trace只打印getMessage()),而不管什么level,都写入一个通用log文件,对exception直接printStackTrace()。”?
这个需求,hehe,怎么说,实现起来非常简单。 这里仅演示SimpleLayout的情况(Log4j一共也没几种Layout,搞一圈也不花工夫) package org.charon.log; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.SimpleLayout; public class SimpleLayOutIgnoreException extends SimpleLayout { public SimpleLayOutIgnoreException(); {} public boolean ignoresThrowable(); {return false; } } 然后定义一个log4j.properties: #1 定义了两个输出端 log4j.rootLogger =INFO,A1,A2 #2 定义A1输出到控制器 log4j.appender.A1 = org.apache.log4j.ConsoleAppender #3 定义A1的布局模式为PatternLayout log4j.appender.A1.layout = org.charon.log.SimpleLayOutIgnoreException #4 定义A2输出到文件 log4j.appender.A2 = org.apache.log4j.FileAppender log4j.appender.A2.File = test.log log4j.appender.A2.layout = org.apache.log4j.SimpleLayout 就可以演示了,很简单对不对? 但是,我敢保证,这个东西不是什么实际的需求,只是为了表明某个特性而演示的一个东西。 这只是一个只需要在Layout类中添加一个属性就可以配置的功能(这样一来,就不需要前面的子类化了),但是这个演化了将近十年的工具却没有去走到这一步,只能说明这个需求至少现在还没有人把它当作一个实际的事情。 hehe,前面我那么一点失误,log4j是能够做到某一个级别或者某几个连续的级别输出到一个文件那个需求的,只不过需要用到xml配置文件,用properties是做不到的。 |
|
返回顶楼 | |
发表时间:2005-08-09
ajoo 写道 charon 写道 11-14不存在作的到做不到的问题,比如应该由ajoo你来提供几个Exception类,来打印需要打印的东西(ExecutionTrace之类的),而且,我觉得通过子类化Exception来做额外的trace打印工作,比每个需要特别对待的场景搞一个xxxExceptionLogger要干净。 EvaluationException, NeptuneException都是和logging无关的别的模块抛出的异常。怎么能够让它们和logging的逻辑耦合?如果我调用一个第三方地库,需要在logger里面特殊处理一个XException,难道还要通知这个库地作者改动Exception,因为我的logger需要特殊处理? 难道让那个EvaluationException, NeptuneException在printStackTrace里面捎带着把自己的原始文本的跟踪信息就是和logging耦合了?这个本来就是这几个Exception的职责,不是有NestedException这个好玩意吗?非必要的扩展Exception接口并不是什么好事,至少对于exception的捕获者而言,必须多看几眼才知道这两个exception还有那么特别的方法。万一人家只是最后收底的,直接拿到手里的就是Exception类型,难道还要转型去搞出这些trace信息? 这是很常见的情况: try{ .... }catch(XXX xx);{//捕获可以处理的信息 ... } ... }catch(ZZZ zz); ... }catch(Exception e);{ //捕获本地不能恢复的Exception,EvaluationException, NeptuneException不幸位于此列 logger.error(...);; //log一下 throw new XXXXXXX(e);; //包裹一下,再抛出 } 此时,按照扩展Exception接口的解决思路,printExecutionTrace是一个添加的方法,肯定是不能这么写了 必须一个一个捕获过来,累不累啊。 而且,按照纯粹的做法,要添加方法,先搞一个接口处来,然后再XX. 退一万步,有人就是喜欢这么做,那么,其实log4j有一个非常简单的解决办法,针对这两个Exception实现ObjectRenderer接口不就得了. 引用 另外,说一句题外话,提意见的也好,觉得自己明白了的也好,真诚建议你们动手做一下这些需求。真正动手做了,才能发现自己哪里想得简单了,才能真正体会co的区别。我费尽心机找的这么清楚的需求例子,别浪费了。 题外话其实不必说,有这个时间,多看一点commons-logging/log4j以及java logging api的文档,应该对了解logging模块的真正的需求会有很大的帮助。还是那个想法,对于一个花了将近十年时间演化成熟的框架来说,前面说的那些个灵活性实现起来并不复杂,但为什么人家就不实现? 讨论A是不是比B更爽,只是列举出有一些事情A能干B干不了是不够的,关键还在于A这些特别能干的事情在实际中是不是有意义。说一句实话,屏幕打印,除了在断点调试的时候可能有点用(但我也有很多年没这么用了),正而八经运行的时候,nt下的服务和unix下的daemon,根本没有地方输出。 |
|
返回顶楼 | |
发表时间:2005-08-09
ajoo 写道 只是你的估计。不要小看组合产生的几何级数增长的变化能力。偶尔确实会有要回头增加组合子的需要,尤其是开始的时候。但是增加那么几行简单的不能再简单的代码真的很麻烦吗?
组合的威力是非常巨大。但是也没见到有人尝试着从原子开始组合出一个哪怕是简单一点的昆虫来。这个问题最后又归结到开放空间的搜索,然后又变为机器学习,还会牵涉到动力学/混沌/自组织之类的高深东西。 创世纪的想法很多人(尤其是那些信仰上帝的人工智能前辈们)都走过了,但是,即便只是在机器里面模拟出有一定复杂度并能够自圆其说的世界来,也不是一件简单的事情。人工生命走到后来声音越来越小,也是发现这个做法其实是搞不出什么东西来得。元胞自动机的那几个复杂图案已经是极致了。按照前面的思路,CO的世界是你让它实现的,它就有,你没替他实现的,它不会给你多走一步。远没有元胞自动机好玩。 |
|
返回顶楼 | |
发表时间:2005-08-09
不过仔细想想,CO这个玩意儿还是很有点意思。等回睡觉的时候好好咀嚼一下,看看有什么东西可以吸收吸收。还是gigix说得比较直观。我觉得关键不是CO能够做什么,而是它不能够做到那些事情。只有知道这一点,心里才踏实点。ajoo把这个东西说得像#####一样,的表达能力太@!@#$了,要求向大家鞠躬!!!
就这个logging的例子,我觉得如果好好打磨,在使用接口上CO的做法和log4j能够基本持平,都通过配置文件较为简单的搞定,在内部结构上CO的做法能够更胜一筹,但是在效率上,我想比起log4j来可能会有问题,这也是log4j广泛传播的一个重要原因。还有一个,就是外围工具,现在log4j可是有很多的appender的,太多了。 |
|
返回顶楼 | |