论坛首页 综合技术论坛

TDD + 重构的开发方式下代码可读性的看法:没有最好,只有更好

浏览 32333 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-07-23  
1 只要存在重构的情况,并且重构的方向正确,重构后代码的可读性就必然好于之前的。而且,人的认识是一个渐进的过程,重构也是一个渐进的过程,今天提交的代码,多数情况下是在之后的那些日子重构的。此时,重构之前的代码状态是存在着一些发现或者未发现的味道。这种状态下的代码可读性相对差一点。
重构过程中代码的质量和可读性都可能是越来越好的,但是开发人员看到的是这个过程的代码,而不是终极代码。
2 TDD中的单元测试是针对接口的。不能也不应该去测试复杂算法(比如凤物凰杨所说的那个样条曲线计算)的具体步骤和中间状态。这个时候,这些中间函数和状态都已经超脱了能够用unit test例释的范围。这类算法之精巧、内聚性之强,如果没有提纲挈领的一个说明,仅凭具体的代码,很难理出整个算法的思路。此时的代码不是自解释的。我曾经看过用有限元计算磁场的算法,看书看了两个星期都没有弄明白,如果只看代码,估计一年都搞不定。当然这是一个极端的例子。但是,确实不能指望代码阅读者具备所有需要的背景知识(也不能保证所需要的背景知识都有相应的书本可以参照)。否则,在项目的开发者或维护者中,这样的代码阅读者就是神的化身。
   发表时间:2004-07-23  
另外补充一些“凤物凰杨”不愿意了解的情况。

“我们已经提到过这样的一个事实:在能力方面,人类的头脑有某些来自先天的局限。这些局限可能会因人而异,也可能对于不同的问题也不尽相同。尽管如此,我们还是可以肯定地说,对于同一个人而言,一段短些的程序总是要比一段更长的程序要更容易理解。比如,通过对注释的研究我们发现,即使是添加了几行不会执行的问题——也即使这些文字是明确地为了提高程序的可读性——也会增加程序阅读的难度。”

《程序开发心理学》P308

还有一段也是书里的,我不记得具体的页数了。大义是:为了在调试程序时排除注释的误导,高手们往往会想办法屏蔽掉多余的注释。

另外,在重构里也曾经谈到,通过变量、方法的重新命名,可以删除掉大量的多余注释。
2 请登录后投票
   发表时间:2004-07-23  
charon,我觉得现在还是有很多人没有理解敏捷方法或者 XP 的精髓(甚至是一些向别人宣传敏捷方法的人)。建议大家重新读一下《敏捷宣言》。敏捷方法不是一种新的方法论银弹,不可能解决所有的问题。敏捷方法的精髓是重视人的创造性、通过信任激发出人的创造性。人永远是第一位的,过程永远是第二位的。如果觉得某种敏捷方法不适合你们,完全可以加以裁剪。实际上 Bob 大叔和 Martin Fowler 都是这样做的。以前我读 CMM 的教材时是带着敬畏的心情读的,以为必然会找到我每天诵读 10 遍就能解决一切问题的圣言。CMM 的发明人似乎也希望我们这样想。而读所有关于敏捷方法的书我从来就没有这种感觉,我从来没有认为这些是什么金科玉律。我不过就是在闲暇的时候读一读,发现了有用的思想、技巧马上就在实际工作中用起来。我并不认为 TDD 能解决所有问题,但是在很多场合 TDD 确实是一种很好的实践,对我们确实有帮助,这就足够了。
敏捷宣言 写道
虽然我们相信一组共同的目标和原则有利于敏捷方法的使用者,但是我们同样坚信,具体实践的多样性和差异性是必不可少的。对于方法而言,每个项目都是不同的,每个项目小组也是不同的——没有什么放之四海而皆准的解决方案。
所谓敏捷,就是相信人能够对不可预测的事件及时做出反应,而不是相信人能够先知先觉。

软件研发编辑 写道
Kent Beck 曾经说过,XP 的最高境界就是不再考虑“是不是 XP”的问题。这说明项目和团队具体情况千差万别,敏捷的本质,应该是将敏捷的思想融合到实际项目中,定制自己的方法。
大家了解敏捷方法,最好直接去读《敏捷宣言》,而不要通过这里 potian、o6z、gigix、dlee 等人的只言片语。同样是儒家,对孔子的解释都有不同,你究竟该相信谁的呢?还是自己去看《论语》好了。
2 请登录后投票
   发表时间:2004-07-23  
我前面看到你们在争论什么驱动开发,就想说这话的。

不是测试、不是单元测试、不是集成测试、不是文档、不是用例、不是特性,而是人。人不应该被这些东西驱动,而是应该站在主动的位置上,做取舍。
2 请登录后投票
   发表时间:2004-07-23  
我和庄表伟同志的看法越来越接近了。实际上敏捷方法是把一把刀交在你的手里,告诉你不要去崇拜偶像,只要勤学苦练,终有一天你也可以成为大师。人皆可以为尧舜,我们现在是生活在这样一个时代里。但是对于习惯了 CMM 或者某种方法论银弹,习惯了整齐划一、服从命令听指挥的军事化管理的人,要转到敏捷的思考方法确实需要付出比较大的努力。他们无非是把敏捷方法或者 XP 当作另外一种方法论银弹罢了。
2 请登录后投票
   发表时间:2004-07-23  
agree charon
补充第一点,如果没有一致性的标准,可读性有可能因人而异。因此应该注意在团队里建立接近一致的标准。至于团队外的人员,有空再说吧。 ;)
2 请登录后投票
   发表时间:2004-07-23  
charon第二点更不应该写注释了,既然你看书看了两个星期都没有弄明白,看代码1年搞不定,那么看注释1百年也搞不定

碰到这种情况比如凤物凰杨所说的那个样条曲线计算的例子,我会给方法取一个教科书上或论文的算法名字,例如XXXX算法,读者直接可以根据这个名字搜索google或者教科书,或者没有间接的名字,最多注释一下来自哪本书那一页

当然,如果这种算法是你自己研究出来的,恐怕你也需要写一篇论文而不是注释就能搞定的。

注释一般在实现的方法比较微妙,有各种权衡,你选择了其中的一种,或者业务逻辑比较纠缠(而不是那种纯粹的数据或什么算法),而你又很难通过重构或者你现在因为各种原因不能够重构的时候,或者你现在实现得有漏洞,有限制,目前又可以用,等等情况。如果纯粹是增加理解,代码自身好得多,如果代码不能解释,注释更加无能为力。

如果要我提忠告的话,那么就是:

如果在你写注释之前,没有先去重构而是先去写注释,那你完全丢掉了让程序结构更好,让你的水平更高,让你总结更多经验的机会,

日以累计,你越想通过注释去解释而不是代码去阐述你的意图,你的代码结构将越来越差,表达能力将越来越烂,最后你的所有代码将成为泥潭,可能真的成为需要雇用大量写注释的对象(当然,如果我是领导,我肯定叫别人来重构),或者索性被扔掉。
2 请登录后投票
   发表时间:2004-07-23  
很多时候实现的都不会是标准的算法,针对具体问题或多或少都会有些修改,虽然算法的实质还是那个。
不过确实,这类项目中对某些算法的应用,或者自草(不是自创,绝大部分时候那种自己设计的算法肯定都被别人想到和实现过)了一些算法,最好的地方还是在相应的文档中,而不是注释里面。但是这个时候,代码显然已经不是自解释的了。不存在一个可读性的讨论。或者说每一行我都认识,但是这些东西组织起来到底在干嘛,这样一个big picture,必须结合外部的东西才能理解。
1 请登录后投票
   发表时间:2004-07-23  
一个算法被映射到软件语言中,需要对其映射是否合乎其含义进行验证,这是一个必须进行的工作。如果一个算法存在与其相逆的算法,也就是通过对结果进行逆推可以得到深入,则这个时候这个映射可以进行逆算法的验证,而这个验证可以自动化的进行。
另外还存在一种算法,不存在逆算法,例如很多安全方面的算法。这个时候进行的验证就只能是不完全的自动化进行的。我们主要应用的方法是使用一个已经得到验证的别的语言的算法,进行一系列的计算,把输入和输出进行记录,成为两个对应的表格。然后把实现的语言环境下,使用这两个表格进行对比,当输入和输出的对在某些时候不能与原来得到验证的测试相一致的时候,就是失效出现的时候。
而不管你使用什么验证的算法,对于算法都不需要编程者必须理解的问题。很多时候软件中使用的算法是非常复杂,并且几乎不会被任何没有专门数学背景的人理解。这个时候你采取任何发生都不能解决其可理解的问题。
从本质上来说,一个算法根本就不需要程序员去理解,只需要程序员验证是不是按照算法的要求实现了这个算法。
同时我再一次强调TDD中的测试不是unit test,相关内容可以参考任何一本基础性的关于测试的书籍。
0 请登录后投票
   发表时间:2004-07-23  
o6z 写道
同时我再一次强调TDD中的测试不是unit test,相关内容可以参考任何一本基础性的关于测试的书籍。

我现在总算看懂 o6z 说的话了。以前 keys 做 XP 时候告诉我们 TDD 做的就是 unit test,这个误会我一直带到今天。o6z 说的没错,如果把 TDD 狭隘地理解为简单的 unit test,确实会对 TDD 的功效产生怀疑。TDD 并不是传统意义的 unit test,还包括分析、设计在里面,甚至包括一个迭代中的所有活动。
0 请登录后投票
论坛首页 综合技术版

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