上台一鞠躬。是的,久别两个月我又回来了。
最近忙着杂七杂八的一堆事,不过基本都是维护老项目代码了。一说起这个亘古不变的老话题,估计许多人都要开始抱怨了吧:没有格式没有篇章的混乱、没有甚至是错误的注释、没有说明文档……“我可写不出这种天才代码”、“实在太难看了,我要重构”之类的话我已经听不少了。
读代码难,但写代码也不见得很容易。老代码们都有着他们自己的项目背景,经手的人也多,日积月累自然而言就变成了现在的样子了。重构——说是很容易的——先不论我们的能力跟当时开发者相比孰优孰劣,他们会写出这样的代码总有他们的理由,只是经过时间的磨蚀,当时的缘由我们就不得而知了。
重构不是对付老代码最好的手段。重构首先会遇到最大的问题,就是刚才提到的项目背景,大多数的老代码除了满足基本需求功能,后期还会不断临时加入满足某些用户需求的特殊功能,若对这些不了解就轻易地重构,势必造成代码功能缺失。
之所以那么多人要重构老代码,因为我们都对它恐惧。而恐惧,则是源于我们对它的不了解。维护老代码时,我们怕破坏它的功能、怕造成程序的不稳定……我们维护自己的代码时,何曾会怕这怕那的?希望对老代码进行重构,不过是因为我们想把它变成自己的东西、方便自己操作而已。可一旦交接给下一个人,没准他又开始喊着要重构我们的代码了吧。
老代码告诉我们的是它的基本的样貌,不到万不得已,不必通过重构对它进行整容。我们只需要使用测试用例,去矫正它在岁月中留下的伤疤。
事实上,我们也应该强迫自己持续地给老代码做测试。刚开始这样做,可能会使得进度缓慢,但长期下去,我们就会有足够的测试用例,这除了使得老代码的功能可以更健壮,也使得我们对老代码更有信心,无需再过度担心维护代码时带来的副作用。
打个比方,举重运动员为了变得更健壮,日积月累地训练,终于使得腿部筋腱开始出现断裂。不过他认为持续的锻炼会使自己最终适应这种痛苦。但正如他每次下蹲都要忍受疼痛一样,没有测试用例的老代码在各种新功能附加的重压之下也开始出现扭曲、变形。后来医生告诉他应该重点做康复锻炼,因为只有在复健后,他的肌肉会变得更结实、能够承担更多重量。同样地,针对老代码的既有功能补充测试用例,可以使得老代码更健壮,当以后交接到别人手上的时候,重构的呼声自然也就会减少了。
不过有的时候,我们拿到手的老代码是已经有一定的测试用例的了,它们也能运行成功,但是这些测试却对理解老代码毫无帮助——有些测试是为了图方便而建立的,它们之所以能运行成功,是因为这些测试都是在假设代码能够顺利运行的理想情况下建立的——我们不需要这种花瓶式的测试用例。
其实最理想的情况,就是测试用例可以完全覆盖老代码,但实际上不可能——我们也不需要那样做——字典上单词都是用到时才去查的,测试用例也一样,不然你有看到过谁把字典背下来了吗?