关于TDD过程中如何让文档同步。
这个问题,后来感觉似乎放在这个板块似乎不大合适,不过这里的讨论我更喜欢些,所以还是放到这里了,希望o6z别“砍”我,我发现0分的帖子讨论的人更积极些也更纯粹些。
我在实践TDD的过程中,一直有这样的疑问和麻烦在困扰我,首先,这里说的文档主要还是JAVADOC文档,抛开其它的从to do list开始的TDD的实践,我们知道,TDD总是秉承这样的迭代(细节不必细扣):
Add a little test.
Run all tests and fail.
Make a change.
Run the tests and succeed.
Refactor to remove duplication.
在这个过程中,我们看到,设计是很容易改变的,设计总是在随测试用例的添加不断更新,在完成一次迭代的最后一步重构中,更是可能会产生翻天覆地的变化(注:这里当然如果熟练,一开始就有好的框架和设计总是可能的,不过按照拥抱变化的原则,翻天覆地的变化也并非不可能),这个中间必然有一个JAVADOC文档同步的问题。
大多数人会选择先写JAVADOC文档,而后再修改代码,但是这个工作量仍然是很大的,可能超出自己能忍受的范围,为什么呢?考虑这样的状况,为了保证迭代的持续性,我们通常采用自己所能控制的最小步骤来进行重构(或者开发,为了好说明,我后面就只说重构的状况下,因为相对普遍些,也省力点),这样,一个方法甚至一个类,它可能只是我整个重构完成后的一个中间过程,比如对于a方法,第一次重构中产生了它,接着第三次重构中我把它去掉了,然后,很可能在后面的又一次重构过程中它又回来了,而且随着重构的深入,可能a这个方法的意义也在进行演化。
我相信,在一小组重构(多次小重构组成)开始时我们大脑里面是有一个大概的目标的,但是这个目标可能并不是那么明确的,因为毕竟还没有实现的,我们总是不好说一定会这样,如果一定会,那么这一小组重构就没有必要细分多次小重构了。
好了,现在问题出来了,由于a方法的反复,我们如果仍然在每次重构a前先写JAVADOC文档,就会出现很多看起来似乎很多余的动作,不断地删除(当然,你可以只是注释掉它)又加回来,然后还要一点一点记录a方法本身的演化过程,很多中间过程在最终结果看来似乎价值不大,注意,这个过程中代码的反复添加删除修改在工具的支持下反而代价极小,所以,虽然是一组重构,但是其实完整这一小组重构花的时间并不多。
我们是在每次重构前都不厌其烦地停下来修改JAVADOC文档先呢(这样做让重构的时间成本翻好几倍可能)?还是很快地完成了这一小组重构再去修改呢?又或者,一开始就按这一小组重构目标所规划地来再必要的地方先加好JAVADOC文档(这个,好像不太好,^_^)?
上面这个问题在你熟练重构和设计状况下还好些,出现的可能并不大,还有一种重构,在设计中,突然你发现需要改动框架了,这个时候,问题就比较严重了,比如你需要在一个顶级接口中添加一个方法,或者根本是要让顶级接口的方法有一个全新的面貌,这个时候的重构可能做不到一蹴而就,而是一点一点地修正,同时还可能要重构很多的unit test,这个时候,是满世界去修改JAVADOC文档先呢?还是利用工具的优势,让代码很快地修正?老实说,这个诱惑还是很大的,因为我们总是想在最早的时间让所有测试通过的。很多时候会这样,测试都通过了,然后,呼一口气,心里想看来程序是按照自己的想法在跑了,然后一点一点地修正所有的JAVADOC文档。如果反过来,开始修改JAVADOC文档,似乎很容易中断自己的思路,因为好像是要把设计翻译成中文一样。
之所以会有这样的困扰,主要是在《测试驱动开发》中,一路跑下去,没有关于JAVADOC文档的内容,从头到尾提倡:多跑测试,让重构和变化在自己控制范围内产生,以使所有测试能在大多数时间内都是通过的,如果有不通过的,也要在第一时间让其通过先(这个重点),而使用重构来改善代码结构(在需要一个新方法时,总是让这个方法返回一个写死的预期值来满足当前测试,然后在重构中完善它,这一点我印象非常深刻)。
不知道大家都是怎么处理这个问题的。
另一个是unit test的javadoc文档应该如何写,看JUnit代码,其中测试用例的javadoc几乎没有,反而存在不少非javadoc的注释;通常我会把to do list放进去,但是现在看来这样做并不是很好的选择,因为当需求膨胀的时候,to do list也会膨胀地离谱而难以维护,这一点也请有实践经验的朋友谈一谈。