2012年06月09日 16:05供稿中心:兆隆教育
你的代码写得怎么样?如果你不属于平庸的80%,我敢打赌你的代码一定写得很棒。也许你正在维护遗产代码(不再被广泛支持的系统相关的源代码),这些代码究竟能有多糟糕?情况会有所好转吗?虽然有一套方法可以帮助评估你的代码,然而并非每个人都对此表示认可。
优点
我个人认为评估数据非常有用。通过类似Emma这样代码覆盖率计算工具,能够让你彻底了解你的代码中究竟哪些已经被测试覆盖,还有哪些没有被测试到。在开始着手某个包进行大规模代码重构之前,目标代码的覆盖率究竟如何?这些信息会告诉我,也许应该在改动代码前先提高一下这部分的代码覆盖率。
代码行数是另一个种有意思的数据。当你在遗产代码上工作的时候(谁不是在这样的代码上工作呢),如果你既能够保持开发速度(你肯定还在开发新的功能),又能保持与过去相同甚至更少的代码,那么你不但能够在交付价值而且同时还能让代码变得不那么糟糕。任何一个傻瓜都能够写出成堆的新代码以完成新功能,但是真正的高手能够在交付新功能的同时减少原有的代码。
缺点
任何数据都会面对一个问题,那就是利用这些数据的人。你最不想看到的恐怕就是过度渴望监控这些数据的经理了。
不能度量就无法控制。– Tom DeMarco
在你得到数据之前,报告缺陷数量就已经和奖金挂钩了。还有可能大家都希望代码覆盖率能够达到某个"期望值".
只要管理层用数据作为目标,聪明人就会利用系统作弊。我已经数不清有多少次看到人们对代码覆盖率造假了。虽然初衷很好,但经理们受到错误思想的误导。为了讨经理开心,开发者会不断编写没有断言的测试。当然,代码依然能够运行而且不会出什么大问题。但这种行为有意义吗?天知道!当你的代码引入了新bug,那些测试能够检测到吗?见鬼,当然不会!因此,这种代码覆盖率毫无用处。
尽管达到了指标,但是潜在的目标即改进软件质量却被忽视了,而且未来也不会达到。
丑陋之处
任何评估的目标都是评测代码并从中得出有意义的数据。以代码覆盖率为例,我们真正感兴趣的是缺陷覆盖率。也就是代码中的所有可能的缺陷,有多少缺陷能够在测试中被发现?我们想知道,能够在怎样的程度上能够避免重写代码。
问题在于,我怎样才能衡量一个系统中"所有可能的缺陷"?基本上这是不可能知道的。为此,我们使用代码覆盖率作为近似。考虑到测试能够保证代码运行得到正确的结果,因此被执行代码率是对能够捕捉到bug数量的一个很好的预测。如果我的测试执行了50%的代码,最好的情况下我们能够捕捉到50%的bug.如果bug出现在另外50%的代码中,那么通过我的测试捕捉到这些bug的几率为0.代码覆盖率是测试覆盖率的一个上限。但假如你的测试代码很差,那么相应的测试覆盖率也会降低。至于没有断言的测试代码,它们基本上毫无用处。
这就是测量数据困难之处:测量那些真正管用的数据即我们的软件的质量。即便有可能,也是非常困难的。因此,我们要尽可能地进行测量,但并不总是能够清晰地知道哪些内容与我们真正目标相关。
这些数据意味着什么?
有很多类似Sonar这样的优秀工具能为你的代码进行各种常用的数据评测。通常的问题在于,开发者并不了解(或者在意)这些数据的含义。类的复杂度是17.0是好还是坏?我的代码关联系数是5.6%,但是也许有更好的理由这么做。怎样的数据对这段代码而言才算是合理的?LCOM4(缺乏内聚性的方法指标)是好事还是坏事?坦率的说,这听起来更像是治疗癌症。
当然,如果我足够积极主动的话,我应该能够深入并且了解每种数据的含义,并且试着达成合理的目标,等等等等。拜托,我正忙着给客户交付有价值的工作,没有时间扯淡。这些数据是在让人难以捉摸,索性忽略掉好了。当然,领导们不这么认为。
一种更好的办法
一定有一种更好的办法来评估"代码质量".
1. 达成一致
无论你评估的是什么,评估的内容一定要得到团队成员的赞同和理解。如果团队中有一半的人表示反对,那么评估的结果一定不会很好。一些人努力想要改进,而其余的人则会让事情变得糟糕。实际效果一定会让人大失所望。
2. 评估最重要的部分
不必评估"标准"的内容,像是代码覆盖率或者圈复杂度。只要团队成员一致认为这是一项有用的数据,每个人都认为需要在这个方面改进并且做出承诺,那么评估它就是有用的。
我在youDevise的一个同事,花了10%的工作时间构建了一个可以跟踪评估数据并能够以图形的方式展示结果的工具。然而,非常特别的是,这个工具并没有计算很多大型静态分析工具给出的那些常见评估数据,而更多地统计了更加常见和具体的问题。那么,哪些是更贴近自己且更容易评估的呢?
? 如果你有一个上帝类,那么可以统计文件的代码行数,行数越少越好
? 如果你有一个想要避免使用的第三方函数库,那么可以统计使用它的次数
? 如果你有一个想要移除的类,那么可以统计引入这个类的次数
这些简单的测量代表了我们真正想要摆脱的技术债务,通过减少技术债务我们能够改进自己代码的质量。与此同时,评估的方法也会异常的简单,最直接的方式只需要执行grep和wc命令就可以。
评估什么并不重要,只要团队相信你评估这些内容会得到改进。通过评估你们关心的内容,你会真正了解到你的代码质量。
3. 让结果更直观
最后,请把评估结果贴到显示器上,与实际构建状态越接近越好。这样每个人都能够看到你正在做什么,并且能够不断提醒人们质量的重要性。反馈是非常重要的,你能够看到事情正在朝着更好的方向发展;同样重要的是,当质量开始滑坡时,数据图能够把问题上升的趋势展示出来。
简单,明了
代码质量是一个非常抽象的概念,因而很难测量。因此,你应当转而关注那些容易评估的东西。评估内容越简单、越容易理解,改进起来也越容易。如果你需要花时间解释这些评估的意义,那么这里肯定有问题。尝试一次只关注一部分内容,如果你同时关注100项不同的数据,让这些方面都能够得到改进几乎是不可能的。如果我们只关注其中的几项,我就能记住他们,至少不会让它们变得更差。我有可能把它们清晰的记下来,这样才能够改进它们。
你在评估自己的代码吗?如果是的,你评估的内容是什么?如果不是,你认为可以评估哪些方面呢?