该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-04-04
如果的事情就不用谈了, DHH说假如当初没有先看见ruby他大概也会去用python写rails. 那样的话现在python可以一脚踢开java横着走了
interface我一直认为只是静态类型和OO的折衷的产物,不是OO的必须要素. 动态类型如果要明确声明接口那method_missing又怎么实现呢? 灵活性总是要有代价, 只是要看这个性价比合算与否. 我同意你说的很少人看测试来用代码的,因为测试包含很多边界情况,而不像文档中只包含正常情况. 当然通过文档来约定如何使用不能像interface那样获得编译期检查. 但是真会出问题么?不会啊. Bruce Eckel早就写过文章谈过这个问题了. |
|
返回顶楼 | |
发表时间:2006-04-04
Strong Test实际上是很难达到的。
我曾经在Robert Martin的“敏捷软件开发”中的保龄球例子中找到过很明显而且严重的逻辑错误,有人据称在后面的更加复杂的例子中找到过更为恶劣的逻辑错误。那是一本以TDD来讲敏捷的书。 当然,这类错误不论在静态类型语言还是动态类型语言都会出现,我只是想说明,彻底、或者不那么彻底但够用的测试是很困难的。尤其是涉及到多个对象的合作逻辑的时候(当然,easymock是一个很漂亮的工具)。单个方法的工作方式可以预期,但是一旦交织(因为现在都倾向于编写那类短促的方法,还有一些人喜欢重用,所以这类交织的频率就更多),那就是在考验开发者的逻辑思维和想象能力了。我一直觉得je上的大伙对程序员的测试能力太乐观了。 实际上,从某种意义上来说,我们需要进一步强化测试的手段,而不是弱化。那么,有必要取消静态类型检查么?毕竟,这是一种更加廉价的测试。 谈到接口,我觉得这是一个关键性进步之一。从解耦的角度来看,接口提供了调用者和实现者之间的一个支点,使得契约得以不依赖于调用者和实现者而独立存在。这是一种非常自然和直观的思维方式。曾经我对针对接口的契约定义(比如通过annotation)和测试非常感兴趣,但后来俗事太多... 而且,接口本身和missing-method是没有关系的,但它可以添加强制约束。 一个抛弃接口的动态强类型语言,只是返古。但是,想要在动态类型语言中引入接口,同时又要保持语义模型的一致性,是件不容易的事情。 |
|
返回顶楼 | |
发表时间:2006-04-04
尽管静态类型检查确实比较廉价,因为你必须测试,所以区别已经不大了
在Ruby里面类型是duck type,也就是说如果我只关心你的叫法和你的走路方法,那么只要你象鸭子一样嘎嘎叫,像鸭子一样蹒跚走路,那么我就把你当作鸭子。 例如我很关心我女儿的身高,有一天突然发现我女儿比桌子高了,我就比着凳子和我女儿说,“你看原来你只有这么一点高”,又指着桌子说,“看看,现在比桌子还高了”。只是为了比一个高低,桌子、凳子、我女儿(小孩)没有必要去实现一个hasHeight这个接口,只要他们都有Height就行了。 |
|
返回顶楼 | |
发表时间:2006-04-04
这里就有一个偶然性等同问题,如果碰巧两个对象都有同名方法,但是语义不同,在这种情况下都是可以去搞一下的。
比如,人和人XXX,狗和狗XXX,假如都是用xxx这个方法。就很容易出现人和狗xxx这样的事情。而且,测试的时候也很难用简单的方式发现到底是哪两种东西在xxx. |
|
返回顶楼 | |
发表时间:2006-04-04
potian 写道 对重新命名之类的重构可能工具会起到作用。
但是实际工作中的重要重构都是需要手工操作的。例如最常见的重构方法是抽取方法、抽取抽象类或成员在类之间的转移。很多时候抽取方法通常不能整段整段地进行,而是需要先从相互纠缠的代码整理出一段干净的单责任的代码,加上冗余的变量,然后先抽取一段成一个方法,进行测试。接下去再对剩余的代码重复上述过程。这个过程基本上工具是很少有用处的,除了一切都准备好以后抽取那一下,但就算这一下,很多工具也是不合意的。 这种重构往往在整理单责任代码的同时伴随着配置的修改,class的rename和move等动作,甚至包括class调用关系的调整。这里抛开ruby,只看Java,就算单元测试代码齐全,无论如何Eclipse能够给我提供的帮助远远超过UltraEdit。目前我面临的问题是,我希望重构能够把XML配置一起放进去,否则XML我总是要重新review一遍,严重影响重构的信心,因此产生了使用Java来表达配置信息的想法。 总之,我认为对于静态类型语言例如Java来说,这种类型严格定义可以让Eclipse这种IDE帮我们做很多很多事情。我不认为在UltraEdit里面rename,move是一件很轻松的事情。 |
|
返回顶楼 | |
发表时间:2006-04-04
charon 写道 这里就有一个偶然性等同问题,如果碰巧两个对象都有同名方法,但是语义不同,在这种情况下都是可以去搞一下的。
比如,人和人XXX,狗和狗XXX,假如都是用xxx这个方法。就很容易出现人和狗xxx这样的事情。而且,测试的时候也很难用简单的方式发现到底是哪两种东西在xxx. 很简单,大部分动态语言都有方法在运行期判断对象的类型(ruby用kind_of?). 人和狗是不能xxx(除非程序员想这么干,编译器能查出这种大逆不道的语义么?),但还有很多别的共性巴,毕竟大家都是动物嘛哈哈.强类型的麻烦就是所有这些共同的部分都要重复处理. 我前面说了,这是灵活性和性能的不同权衡. |
|
返回顶楼 | |
发表时间:2006-04-05
charon 写道 其实我对ruby最大的迷惑是没找到接口在哪里。虽然之前的动态语言确实是不需要接口的。
我一直觉得单元测试很难保证使用者按照类的编写者所设想的正当方式来使用那些方法,毕竟不是很多人都会去看着测试用例写调用代码。而接口可以被看成是契约的一种表示,并且它是抽象的,不会受到具体实现的困扰。 动态语言使用上的巨大灵活性,使我感到仅仅靠单元测试很有点力不从心。应该说,现有的测试工具对于广泛使用诸如closure之类结构的动态语言而言,存在着阻抗不匹配的现象。 对于重构,我赞同potian的看法,除了在涉及到包/类/方法重命名的时候,使用工具确实非常轻快之外,其它的很多场合,使不使用对效率并没有显著的影响。 对于ruby的duck typing来说, 的确无法保证charon所要求的东西, 不过看问题也要分两面, 失去什么,得到什么, 分析起来, 我觉得ruby还是划算的... |
|
返回顶楼 | |
发表时间:2006-04-05
对XML我也没什么好感。不过很多时候是因为被滥用了。
一个原因是用作不恰当的地方,譬如ANT,明明是编程,为什么要用XML,复杂程序的构造过程可能和很多系统、外部工具、编译器打交道,或者要获取外部资源,用XML写只能在别人提供的功能内打圈圈,或者自己写插件。譬如我们的集成构造过程失败需要向我们自己报警服务器发送一个报警信号,这个报警服务器根据预定义的规则会触发警灯、语音播放、email、短消息等等。我非要去写个什么publisher插件,传送参数也麻烦的很,解析来解析去,写得对不对还不知道,动作被生生割成两块。如果象rake只需要一句简单的socket发送即可,所有的上下文全部都在程序里面,谁提交的,什么构造问题等等之类的。 另外是分散和重复,象Hibernate的XML就属于重复工作,万恶之源莫过于重复了。还有像Web.xml的filter配置,为什么不用annotation或者象Rails一样和代码写在一起。不过对annotation我也没什么好感,那是另花。 还有就算用作配置有时候也不够动态,特别是和系统业务相关的配置,一开始觉得这些配置不会变,用了XML,结果呢,需要动态增加或删除,放在数据库里面才是正道,当然为了CVS的方便,可以用脚本维护。 还有就是太复杂,根本没有层次的配置文件,用properties比XML好得多。就算有层次的,要生成对象的,绝大多数YAML也比XML好,易读,清晰。 |
|
返回顶楼 | |
发表时间:2006-04-05
cookoo 写道 如果的事情就不用谈了, DHH说假如当初没有先看见ruby他大概也会去用python写rails. 那样的话现在python可以一脚踢开java横着走了
ror中把方法映射为url的方式和CherryPy是一致的,应该是参考了CherryPy,可惜没有用Python写rails |
|
返回顶楼 | |
发表时间:2006-04-05
robbin 写道 potian 写道 对重新命名之类的重构可能工具会起到作用。
但是实际工作中的重要重构都是需要手工操作的。例如最常见的重构方法是抽取方法、抽取抽象类或成员在类之间的转移。很多时候抽取方法通常不能整段整段地进行,而是需要先从相互纠缠的代码整理出一段干净的单责任的代码,加上冗余的变量,然后先抽取一段成一个方法,进行测试。接下去再对剩余的代码重复上述过程。这个过程基本上工具是很少有用处的,除了一切都准备好以后抽取那一下,但就算这一下,很多工具也是不合意的。 这种重构往往在整理单责任代码的同时伴随着配置的修改,class的rename和move等动作,甚至包括class调用关系的调整。这里抛开ruby,只看Java,就算单元测试代码齐全,无论如何Eclipse能够给我提供的帮助远远超过UltraEdit。目前我面临的问题是,我希望重构能够把XML配置一起放进去,否则XML我总是要重新review一遍,严重影响重构的信心,因此产生了使用Java来表达配置信息的想法。 总之,我认为对于静态类型语言例如Java来说,这种类型严格定义可以让Eclipse这种IDE帮我们做很多很多事情。我不认为在UltraEdit里面rename,move是一件很轻松的事情。 在xml引用的几乎都是类名,而类名的重构是可以波及到xml里面的,不管是移动还是重命名(至少在idea里可以)。 |
|
返回顶楼 | |