锁定老帖子 主题:基础知识: 需求!
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-08-22
charon 写道 既然这么说,那么你之前举的那几个ajoo早就点出了透明性的例子,完全是南辕北辙。那几句话都说明不了ajoo曾经指出过语义透明,只是说明ajoo点出了函数里面干的活对client的透明,或者说函数的调用者不需要了解被调用函数究竟怎么个实现,这个,只是个常识,信息量等于0。 这个难道不是语义的透明吗? logo 写道 你显然误解了readonly的意思了。readonly这里只是举一个例子而已。在实际用Java开发的软件项目中,类似的需要延迟创建,或者预创建对象的时机选择会经常碰到,这不是性能问题,而是一个根据不同的应用场景进行权衡,采用不同对象创建时机的问题。而按照ajoo的原则,显然在工厂方法里面不能够确定创建时机,必须把创建时机放在外面,因此结果就是工厂= new。
这里,我觉得一个对象由状态的可能性比较大,但像ajoo举例的那种语法分析对象,singleton优化可能性也很大,而且并非每个都必须singleton,所以采取instance的统一接口是比较妥当的方案。但为了这个“少数情况”,号召所有的class都使用此规范是否值得,就有待分析了,我倾向于不值得,除非语言提供某些支持。 把话说绝对了,说什么必然=new,我是反对的,讨论需要严谨,没有正当理由一棒子打死不能说服别人。 |
|
返回顶楼 | |
发表时间:2004-08-22
cat 写道 charon 写道 既然这么说,那么你之前举的那几个ajoo早就点出了透明性的例子,完全是南辕北辙。那几句话都说明不了ajoo曾经指出过语义透明,只是说明ajoo点出了函数里面干的活对client的透明,或者说函数的调用者不需要了解被调用函数究竟怎么个实现,这个,只是个常识,信息量等于0。 这个难道不是语义的透明吗? 如果ajoo所谓的语义透明只是这个的话,后面就没有那么多争论了。ajoo所指的不透明的例子,在函数的角度来看仍然是透明的。 |
|
返回顶楼 | |
发表时间:2004-08-22
看来这里的透明性有很大的分歧。正如firebody所说:
firebody 写道 ajoo为了将他的观点完善,拼命的加了“透明”这个词源进来,什么才算”透明“?按照透明这个概念说下去,还有“半透明”,“四分之一透明”等等的说法了。
难道为了使用ajoo所说的静态函数方法代替构造器,我们还需要仔细而慎重的研究哪个透明,哪些不透明???我敢说,在实际项目中,做这个所谓透明度分析,没几个人能够理的清楚。 要给一个严格的定义看来很难,可能真有一个程度的问题了。我搞不出来了。但即使真的出现外界singleton一个已经通过重构在内部singleton的对象,也没什么大不了的。对于Byte这样的对象做butterfly业是很普遍的(比如C/C++中的某些isspace/isnumber等is函数是通过查表实现的),内部有权对他们做一些处理。 ajoo讨论这个的目的大概是为了在某个将来的语言里用静态厂全面替代ctor,而大家则是基于现在的Java语言的实践,当然会有较大分歧。不过我不认为这个问题不适合讨论,毕竟这样的东西最后也是要付诸实践的。搞清楚它的利弊还是很有好处的。 robbin 写道 他们不愿意在这里置疑ajoo的观点
我当时觉得我的想法还有问题,所以没有立刻来这里发表意见。我挺关注逻辑的严谨的,不过常常还是会出漏洞 :p 至于另一个家伙,我就不清楚了。 如果ajoo没什么值得继续讨论的发言,我也觉得可以结束了 |
|
返回顶楼 | |
发表时间:2004-08-22
cat 写道 把话说绝对了,说什么必然=new,我是反对的,讨论需要严谨,没有正当理由一棒子打死不能说服别人
我只是说readonly举的这个例子,按照ajoo的原则推下来,工厂会必然退化为new,这一点你也没有否认吧。我并没有说在任何场景下,工厂都会退化为new。 |
|
返回顶楼 | |
发表时间:2004-08-22
potian 写道 所以我不准备在讨论下去了
firebody 写道 我也宣布退出讨论!
呵呵,显然ajoo的观点虽然遭到了JavaEye的围攻,在abp也受到了置疑,但是生命力之顽强已经远远超过JavaEye众人所能够承受的心理极限。 对于ajoo来说,最好的尊重体现在耐心的和他一板一眼的较劲下去,而不是狂批一通就闪人,不过显然JavaEye的众人由于不具备和ajoo同样的思维认知基础和交流基础,已经失去了耐心交流的可能性,心理已经彻底崩溃掉了。看来能够和ajoo心平气和交流的非abp的人莫属。 独角戏是唱不起来的,看来如果预知下文如何,我们只能够在abp里面继续讨论了: http://www.allaboutprogram.com/viewtopic.php?t=2209 |
|
返回顶楼 | |
发表时间:2004-08-22
ozzzzzz 写道 其实很多东西就是逻辑上是成立的,但是实际上是无用的,同时也存在逻辑上是不成立的,但是实际上是有价值的.作工程和做学术分歧就在这里,学术永远要以逻辑为主,工程永远以价值为主.这就好像我十分讨厌静态这个修饰,但是我一样会没有感情障碍的单例.说来说去ajoo的方法在我们应用的绝大多数场景中就成为静态工厂==new,而这样的讨论如果在一门以学习语言的讲课中去进行就很合适了.
这个同意,而且比如Exception Specification就是一个例子。不过基于现在的经验来评判一个新的东西是否有用,而不是基于严谨的逻辑来讨论我认为也是不合适的。在严谨的逻辑推断出他没用这个结论时,他没用的可能性,比仅从现在的经验来“判断”出他没用这个结论时,他没用的可能性要大许多。 如果逻辑无法证明他没用,那不妨一试,说不定真有用。 |
|
返回顶楼 | |
发表时间:2004-08-22
cat
我可能要跑题了,不过这样的跑题在此时此刻是有必要的。 工程学从来都是有两个难题,一个是设计一个工程,一个是建造一个工程。设计就必须依靠数学和经验,必须合乎逻辑。但是这些非常合乎逻辑的设计未必就是都会被去实现的。对于今天的静态工厂来说,情况就是如此。ajoo的至少已经为我证明静态工厂是一种可以工作的方法,但是这对于我们这些以工程派来说(不是想党争,而是确实这个词更能很好的说明我们这些人的思维方式)没有任何实际的价值。我虽然是一个重构的狂热者,但是我还是不敢随意的修改已经证明在工作的代码,也不会随意改变已经养成的习惯。至少在我们这里IoC已经是深入人心,大家习惯在各种各样的spring(双关语,另外一层意思是斗地主中的春天)们中生活。让我们来接受一种新的方式,就必须证明其存在的是别的东西不可能代替的,或者是比别的东西更加便宜的,最少是在某种特定的场景下其唯一选择的必须性。然而ajoo这些还都没有做到。 其实就我来说(我想javaeye的多数人也包括参与反对ajoo的人)我们并不反对ajoo的学术观点,我们只是不明白他的这些观点在实际的项目中有什么用,能给我们带来什么好处。我们这些人的工程性格决定了我们不会有勇气去试验一个不知道会不会有用的新东西。而同时这些工程性又决定我们可能会在实际中观察到某些不合逻辑的做法确实有效(单例我认为就是如此)。所以现在ajoo唯一能把我们说服的就是找出一个确实存在于实际中的例证,证明其在某些场景下静态工厂比我们现在的做法更加便宜。 而其实就这种工程的态度来说ajoo从来也不缺乏, http://blogs.allaboutprogram.com/index.php?blog=6&title=eleefp&more=1&c=1&tb=1&pb=1 看看这篇他的blog就知道他是很实用主义的。 但是我们这些人现在实在是感觉他在证明 引用 #include机制比现在大多数语言都使用的import机制要好
|
|
返回顶楼 | |
发表时间:2004-08-23
娃哈哈!!!
一早起来, 居然好消息不断。网球拿了冠军; 我连续多少个小时苦恼的:“怎么让这帮家伙懂得我的意思”, 居然一夜之间成为现实了。 终于有人肯讨论“透明”的概念了。 我还惴惴地想着怎么继续解释误会和要求你们解释你们理解的ajoo的观点是什么呢。幸运幸运啊! 不过搞得cat同学也跟着挨批, 很对不住。看来同志们除了鉴别出了工程派 vs. 学术派的斗争之外, 又鉴别出了abp vs. javaeye的斗争。 警惕的作风,居安思危的思想也是值得我们学习的啊。 好了, 闲话不说了, 现在主要问题解决了, 唯一剩下的就是readonly同学这块硬骨头, 以及robbin等同学在此基础上试图证明的static factory==new(在透明的要求下) 好吧。 我来和readonly同学过过招: [list]1。 java语言规范说, 静态成员的初始化是在这个class被load的时候进行的。 那么什么时候第一次load这个class?只有当这个class第一次被引用。 不是在系统初始化的时候。不是如你想当然的那样在“程序启动”的时候。 那么, 在我这个类里面只公开了instance()函数的时候, 请问, 你什么时候会第一次引用我这个类的任何东西? 请证明, 你这个手工lazy init有意义。 2。 其实就算我们假设在一个xjava语言中,singleton的lazy load真有意义。也无所谓。我还真不知道一个系统里面有那么几十个类,每个类占用了那么十几个byte(肯定比类代码占的byte要少得多)会真的造成readonly所假想的问题。很多时候你会发现你把注意力放在了错误的地方。 抛开singleton, 就说flyweight吧。 它倒是真可能在效率上和内存使用上对外界不再透明。另外, 在其它的一些使用adapter, bridge之类的重构方法里,也往往会引入一些额外的辅助对象,增加更多的间接函数调用。这些,都是多少会影响一点模块的效率的。readonly同学对这个效率上的透明性提出了质疑。 要我说, 这是一个非常非常非常优秀的问题。 这不只是一个静态厂的问题, 它是整个软件工程都要回答的问题。 实际上我对一个java人提出这样的问题(感觉上readonly不是做j2me的)有点惊讶, 要是一个c++的拥趸提出这样的质疑, 我是一点也不意外。c++er们本来就是凡事以效率说事的。 让我以同样的效率观点来质疑整个java语言吧(从跟我打架的c++er们那里学来的): [list]1。 gc让我无法自己控制自己对象的释放。这在某些内存要求紧张的系统里是不可接受的。 2。 你什么东西都new, 不让我放在堆栈里, 效率怎么上得去? 3。 Object[]居然是一个里面放满了指针的数组? 搞什么? 这样强迫我多了一个间接寻址, 不是要了我的命? 4。 每个函数都缺省就是虚的? 那么我随便调用一个非final的类对象的函数都要经过多态? 这在效率要求较高的系统可怎么成? 5。用组合来代替继承? 不要忘了, 组合里面有一个forward call, 这可是一次间接寻址, 如果效率要求不允许怎么办? 6。你用配置文件来通过反射构造对象?你不知道反射是效率低下的吗? 7。java的每个cast都有运行时的检测, 这, 太浪费了吧? 8。每个数组成员存取都有边界检查?靠, 奢侈啊! 9。你调用Calendar.getInstance(Locale aLocale) ?你怎么知道它内部是怎么处理的? 如果它是直接new的, 而你本来就那么几个locale, 每次都new不是很浪费? 还是要我自己做cache? 而且如果那样的话,getInstance()就退化成new了,还有什么意义呢? 如果它内部cache了, 那么在系统内存紧张的时候, 我难道还要写信给sun要求发布一个不cache的版本么? 10。本来我new C()就可以了,你非要搞什么ioc, 弄个什么见鬼的抽象工厂接口出来,这一下你需要一个成员变量,需要一个adapter对象,需要一个额外的多态调用,可能需要分配一个额外的对象,......,天啊!如果我的系统效率要求严格,你这一串的所谓高级的ioc设计不是成了一堆垃圾了? 11。每个Object不管三七二十一都有一个数据结构来记录lock和支持synchronized?好嘛。这可是一个大大的空间的浪费呀。如果我的系统最后发现一启动内存不足,是否要跟sun打官司,让他们把这个强制的数据结构去掉?[/list:u][/list:u] 等等等等。这个列表我可以一直列下去。 我一般就简单地告诉那些拿这些跟我叫劲的c++朋友们:java不在乎这些。ok?你要做一个一个cpu cycle都不浪费,一个byte内存都不多用的程序,用你的c和汇编吧。 其实我早就发现, 如果把效率,内存空间, 这些物理指标考虑进去, 几乎没有任何东西可以是透明的。(比如在j2me中,一些我们在j2se, j2ee里面认为不错的技术就不能随便采用,为什么? 就是因为有些具体的硬件限制。) 而如果我们把这些物理指标也当作可见的程序行为的话, 用动态多态来做面向对象这个东西就可以认为根本就行不通。面向接口编程就是一句空话。 唯一可以做的,就是我们都投到c++麾下,用效率与灵活性并重的模板和concept-model编程。 其实, oz的观点本来是我所期待的反应,其实和cat的反映也差不多:行,看上去不错,可是值得吗? 如果我们刚开始就能够在这个基础上讨论的话,也许大家的时间都会少浪费很多。 robbin说我认为“最好的尊重体现在耐心的和他一板一眼的较劲下去,而不是狂批一通就闪人”, 我觉得还要再加上一个定语 “不是问题还没搞清楚狂批一通就闪人” 这也是一个我对potian这么德高望重的人都那么不客气的一个原因。 你们可以看到, 就在最近的几个帖子,potian才弄明白我的意思是什么。而之前几百篇帖子,一直在批驳一个我都不认识的potian定义好的“ajoo”, 还包括一场争吵,都为了什么?意义何在?还迫不及待上纲上线到不懂ocp上去了。 firebody就不用提了,人本身没问题, 但是太毛躁。我干脆不再看包括他的几个人的帖子了,这样至少可以避免让firebody等同学回头又发现无端地浪费了好多宝贵的时间。不是对个人有什么意见,也是觉得其实potian应该已经可以代表相当大多数人了。 其实问题现在说开了(还差最后一点readonly这个硬骨头,我有信心收拾你。 ) ,分歧很清楚。 主要就是oz和cat所说的:值得不值得, 实用不实用。(顺便说一句,我觉得cat和oz的观点那么相似, 不知道这里的某些仁兄为什么偏偏对cat那么不客气? 是不是因为cat来自abp,而稍微指出了各位的一些逻辑错误?) 这点,我个人仍然认为是实用的。在多大范围内应用当然看每个人的权衡了。等这个事完了,我会找时间收拾cat这个都被认为和我是一个党的了,居然胆敢唱我的反调的家伙。就在abp单挑吧。 最后,其实这个讨论真的让我看到了不少这里的问题,不是robbin说的话语霸权而已,而是各位在讨论时候的缺乏耐心,党同伐异,极端主观经验主义(没听过的就是该死的)而不愿意面向逻辑思维和具体实例。 我始终认为,严谨的逻辑思维方式,是不论搞学术的还是搞工程的都需要的基本技能。(对了,我不是什么搞学术的。就我这德行,搞学术?不配) 工程和学术,只不过是一些前提条件的设定不同,逻辑思维的应用上却应该是一样的。 我会另写一篇总结这次的分歧,不是关于技术了,而是关于讨论方法和怎么样学会尊重别人的人格和时间。怎样求同存异。 |
|
返回顶楼 | |
发表时间:2004-08-23
ajoo, 看看第9页第5贴, logo同学的回帖......
偶举你自己的singleton例子, 仅仅是为了从逻辑上证明: 你观点的前提: "对外部透明", 只可能是你在做设计的时候是自己认为是对外部透明 (你认为immutable的singleton是对外界透明的), 随着需求的改变 (有了lazy initialization的需求), 可能会变成不透明. 而不是关注在效率的问题上, 你的回帖里面为什么躲避这个问题, 而越扯越远了呢, 嘿嘿. 同样的你还需要啃掉charon关于黑狗, 白狗的语义说这个硬骨头呢...... 另外: ajoo 写道 那么, 在我这个类里面只公开了instance()函数的时候, 请问, 你什么时候会第一次引用我这个类的任何东西? 你不能限制偶在程序启动的时候, load一些package内部的东东吧: X.class.getResourceAsStream("a.txt"); 你也不能限制偶在程序启动的时候打印出class name来玩吧: System.out.println(X.class.getName()); ...... |
|
返回顶楼 | |
发表时间:2004-08-23
问题是从逻辑上你只证明了自己对java的lazy load理解错误.
你还是好好看看java langauge spec再来拿lazy load说事. 什么拿个class name来玩, 呵呵. 你是程序员还是黑客? 面向接口编程怎么说? 不要关注具体类, 请关注接口. 你不用X.class不行? 有什么灵活性问题? 这时候, 开始无计可施乱找理由, 面向接口的基本原则也不顾了? 其实, 就象那个黑狗的例子一样: 你可以把这个X当作一个提供X指定语义的模块入口就够了. 其它的, 如X返回的是什么类的实例, 包括你这里试图玩X.class, 都没有遵循面向接口的原则, 对不起, 前者不支持; 后者, 你要玩火, 随便. 我也不是东拉西扯,这是鉴于你在吹毛求疵, 我就给你举个例子为什么你是吹毛求疵. 照你的这种鸡蛋里挑骨头, 呵呵, 什么重构手段都有问题. 我可以很简单地依照你的逻辑证明: 1. 重构要求外部行为不变, 内部结构变化. 2. 如果考虑效率, 没有任何结构变化可以保证效率丝毫不变.(连给类改一个名字都有效率差别) 3. 你认为微小的效率差别(如singleton那一点代价)是对外界不透明的, 是外界要关心的. 那么, 可以证明重构是个理论上不成立的伪科学. 你使这招已经是理屈词穷, 开始捣乱了. 而如果你说你不是关注效率, (好像不管我说你是什么, 你反正就是一个反映: no. 也不管是否和你自己说的矛盾 ), 那么, 外界根本没有理由关心所谓lazy load. 为什么? "透明"! 除了, 效率会有微小差别(不过不是你说的singleton的情况), 是否lazy对你外界是透明的. 那个黑狗的例子, 我已经说了, 先列出来, 作为反方的一项理由.(不过当我征求你们战友的意见的时候,却没人响应. 到底你们是否认可这个理由呢? 给个准信儿啊. 别让我回头花了九牛二虎之力解释这个担忧不足以证明static factory没用, 你们来一句: 我本来也不想争论这个, 我不白费劲了?) |
|
返回顶楼 | |