代码度量的魅力是什么?
我最近看到过很多关于“代码指标”的相关问题,不得不想知道这个魅力是什么? 这里有一些最近的例子:
- 什么代码指标说服你提供的代码是蹩脚的
- 如果有的话,代码行数是一个有用的指标
- 编写质量testing
在我看来,没有度量可以替代代码审查,但是:
- 一些指标有时可能指出需要审查的地方
- 指标在短时间内的根本变化可能表明需要审查的地方
但我想不出一个单独的指标本身总是表示“好”或“坏”的代码 – 总是有例外和测量无法看到的事情的原因。
有没有从我忽略的代码度量中获得一些神奇的洞察力? 懒惰的程序员/经理是不是要找借口来读代码? 人们提出了巨大的遗留代码基础,并寻找一个开始的地方? 这是怎么回事?
注意:我已经在回答和评论中的具体线索上提出了一些问题,但没有得到答复,所以我想我应该问一般社区,也许我错过了一些东西。 运行指标批处理作业并不需要再次阅读其他人的代码(或我自己的代码),我只是不认为这是实用的!
编辑:我很熟悉大多数,如果不是所有的指标正在讨论,我只是没有看到他们孤立或任意的质量标准的重点。
在这个线程中的答案有些奇怪,因为他们提到:
- “团队”就像这些指标的“唯一受益者”一样;
- “度量标准”,就像它们本身就意味着什么一样。
1 /指标不是针对一个人群,而是针对三个人群:
- 开发人员:他们关心的是有关代码静态分析的瞬时 静态代码度量 (圈复杂度,注释质量,行数等…)
- 项目负责人:他们关心来自unit testing,代码覆盖率,持续集成testing的每日 实时代码指标
- (他们总是被遗忘,但他们是利益相关者,支付发展的人):他们所关心的每周 全球代码度量有关架构devise,安全性,依赖性,…
当然,所有这些指标都可以被所有三个人群观察和分析,但是每种特定的群体都可以更好地使用每种指标。
2 /度量标准本身代表了代码的快照 ,这意味着什么都没有!
这些指标的组合,以及可能指示“好”或“坏”代码的不同分析级别的组合,但更重要的是,这些指标的趋势是显着的。
这就是重复这些度量标准的真正附加价值,因为它们将帮助业务经理/项目负责人/开发人员在不同的可能的代码修复中优先考虑
换句话说,关于“度量标准的魅力”的问题可以指以下几点之间的区别:
- “美丽”的代码(尽pipe这总是在旁观者编码的眼中)
- “好”的代码(这是可行的,可以certificate它的工作原理)
因此,例如,一个圈复杂度为9的函数可以被定义为“美丽”,而圈复杂度为42的一个长的复杂函数。
但是,如果:
- 后者function具有稳定的复杂性, 加上 95%的代码覆盖率,
- 而前者的复杂程度越来越高 , 加上覆盖率为0%
人们可以争辩说:
- 后者代表一个“ 好 ”的代码(它工作,它是稳定的,如果需要改变,可以检查修改后是否仍然有效),
- 前者是一个“ 坏 ”的代码(它还需要增加一些条件和条件来覆盖它所要做的,而且没有简单的方法来进行一些回归testing)
所以,总结一下:
一个单一的度量标准本身总是表示[…]
:不多,只是代码可能更“漂亮”,这本身并不意味着很多…
有没有从我忽略的代码度量中获得一些神奇的洞察力?
只有指标的组合和趋势才能给你真正的“神奇洞察力”。
我有一个项目,我在一个月前曾经做过一个单项工作,这个工作是为了测量圈复杂性而做的。 那是我第一次接触到这种指标。
我得到的第一份报告令人震惊。 几乎所有的function都没有通过testing,即使是非常简单的function也是如此。 通过将逻辑子任务移动到子例程中,即使它们只被调用过一次,我也能解决复杂问题。
对另外一半的例程来说,我作为一个程序员的自豪感被踢了进去,我试图用一种方式来重写它们,使它们的function更简单,更易读。 这有效,我能够最大限度地降低客户的复杂性门槛。
最后,我几乎总是能够想出一个更好的解决scheme和更简洁的代码。 性能没有受到这个(相信我 – 我在这个偏执狂,我经常检查编译器输出反汇编)。
我认为如果你把它们作为改善你的代码的一个理由/动机,那么指标是一件好事。 尽pipe知道什么时候停止并要求公制违规授予是不可能的。
指标是指导和帮助,而不是目的本身。
我曾经使用过的最好的指标是CRAP评分。 http://www.artima.com/weblogs/viewpost.jsp?thread=215899
基本上它是一个比较加权圈复杂度与自动testing覆盖率的algorithm。 该algorithm如下:其中,comp(m)是方法m的圈复杂度,cov CRAP(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m)
cov (m)是自动化testing提供的testing代码覆盖率。
前面提到的文章的作者(请阅读它,这是非常值得你的时间)build议一个最大CRAP分数为30,按以下方式分解:
Method's Cyclomatic Complexity % of coverage required to be below CRAPpy threshold ------------------------------ -------------------------------- 0 – 5 0% 10 42% 15 57% 20 71% 25 80% 30 100% 31+ No amount of testing will keep methods this complex out of CRAP territory.
正如你很快看到的,度量奖励编写的代码并不复杂,testing覆盖率也很高(如果你正在编写unit testing,而且你应该testing覆盖范围,那么你可能会喜欢随风而过以及)。 😉
对于我的大多数开发团队来说,我很努力地将CRAP得分降到8以下,但如果他们有合理的理由certificate增加的复杂性是可以接受的,只要他们用足够的testing来覆盖复杂性即可。 (编写复杂的代码总是非常难以testing…对这个度量有一个隐藏的好处)。
大多数人最初难以编写能够通过CRAP得分的代码。 但是随着时间的推移,他们编写了更好的代码,问题更less的代码,以及更容易debugging的代码。 无论如何,这是最令人担忧和最大收益的一个。
对于我来说,识别错误代码的最重要的一个指标是圈复杂度。 在我的项目中,几乎所有的方法都在CC 10以下,并且在CC超过30的传统方法中总会发现错误。高CC通常表示:
- 用匆匆书写的代码(即没有时间find优雅的解决scheme,而不是因为问题需要复杂的解决scheme)
- 未经testing的代码(没有人为这些野兽写testing)
- 代码修补和固定无数次(即充满了ifs和待办事项评论)
- 一个重构的主要目标
一个好的代码审查不能代替一个好的静态分析工具,当然这个工具不能代替一套好的unit testing,现在unit testing没有一套验收testing是不行的。
代码指标是另一种放入工具箱的工具,它们本身并不是一个解决scheme,它们只是一个适当的工具(当然还有其他所有的工具)。
有一个我相信的代码指标。
我正在做一个大系统。 当一个新的要求来到我身上时,我开始编码。 当我完成并得到了错误,我检查到版本控制系统。 那个系统做一个差异,并计算我所做的所有更改。
数字越小越好。
我非常主观的看法是,代码度量expression了不可抗拒的制度对能够量化内在地不可量化的东西的迷恋。
从某种意义上讲,至less在心理上是这样 – 你如何才能做出一些你无法评估或理解的事情呢? 最终,当然,除非你对这个主题有所了解(至less和你想要评估的一样好),否则你不能评估质量,或者询问一个知识渊博的人,这当然会把问题带回来一步。
从这个意义上来说,也许一个合理的比喻就是用SAT分数来评估大学入学者,这是不公平的,并且错过了各种微妙的东西,但是如果你需要量化的话,你就得做点什么。
不是说我认为这是一个好的措施,只是我可以看到它的制度上的不可抗拒性。 而且,正如您所指出的那样,可能有一些合理的指标(大量的500多个线路方法,高度复杂性 – 可能不好)。 不过,我从来没有去过这个地方。
人们被吸引到用机械的方式来理解和描述代码的想法。 如果属实,请考虑效率和生产力的影响!
我同意“代码善良”的衡量标准与“好散文”的衡量标准一样明智。 但是,这并不意味着指标是无用的,只是可能被滥用。
例如,某些指标的极端值指出了可能出现的问题。 一个1000行的方法可能是不可维护的。 零unit testing代码覆盖的代码可能有更多的错误,类似的代码与大量的testing。 在发布之前添加到项目中的代码大跃进不是第三方库, 可能会引起额外关注。
我想如果我们用指标作为一个build议 – 一个红旗 – 也许他们可能是有用的。 问题是人们开始测量SLOC的生产力或者testing线路的质量。
度量和自动化testing并不意味着要取代完整的代码评论。
他们只是加快速度。 使用自动检查器,可以很容易地看出你忘记了哪些惯例,你使用的是指定的软件包和方法等等。你可以看到你可以在不使用其他人的时候修复。
pipe理者也喜欢衡量他们,因为他们觉得他们正在获得生产力的确切数字(虽然通常情况并非如此),他们应该能够更好地处理人员。
测量仅在以下情况下有用:
- 团队发展了他们
- 球队同意了他们
- 他们正被用来确定一个特定的地区
一般来说,任何不适合的指标都会受到团队优化的影响。 你想测量的代码行? 天哪,看他们可以写多less! 你想测量代码覆盖率,通过golly,看我覆盖该代码!
我认为度量标准对于识别趋势很有用,事实上,我已经看到了一些有用的方法,比如在构build中断时绘制graphics,代码stream失(整个项目中代码行数的变化)等等。 但是,如果团队没有提出他们的意见,或者他们不同意或理解他们,那么你可能处在一个受到伤害的世界里。
这里是来自stan4j(http://stan4j.com/)的一些复杂性度量。;
一个eclipse类结构分析工具。
我喜欢这个工具和指标。 我把这些指标看作是统计,指标,警告信息。 有时候由于某些方法或某些类实际上有一些复杂的逻辑使得它们变得复杂,所以应该关注它们,检查它们是否需要重构它们或仔细检查它们,因为通常他们是容易出错的。 另外我用它作为分析工具来学习源代码,因为我喜欢从复杂到简单的学习。实际上,它包括一些其他的指标,如罗伯特·C·马丁指标,Chidamber&Kemerer指标,计数指标但我喜欢这一个最好的
复杂性度量
圆环复杂度度量
圆环复杂度(CC)方法的圈复杂度是方法控制stream程图中决策点的数量加1。 决策点出现在if / for / while语句,case / catch子句和类似的源代码元素中,其中控制stream不仅仅是线性的。 单个(源代码)语句引入的(字节码)决策点的数量可能会有所不同,具体取决于布尔expression式的复杂程度。 方法的圈复杂度值越高,testing方法的控制stream图的所有分支就需要越多的testing用例。
平均循环复杂度应用程序,库,包树或包的所有方法中的循环复杂度度量的平均值。
胖指标工件的胖指标是工件的适当依赖关系图中的边的数量。 依赖关系图types取决于度量variables和所选工件:
Fat应用程序,库或包树的Fat指标是其子树依赖关系图的边数。 该图包含了包树层次结构中的所有工件的子元素,因此还包括叶包。 (要在合成视图中查看相应的graphics,必须禁用结构浏览器的平面软件包切换,如果select的工件是库,则必须启用显示库切换,否则必须禁用。
包的Fat指标是其单元依赖关系图的边数。 这个图包含了包的所有顶级类。
一个类的Fat指标是其成员图的边数。 该图包含该类的所有字段,方法和成员类。 (这个图表和Fat值只有在代码分析是用Level of Detail Member而不是Class来执行的情况下才可用。)
图书馆依赖关系的脂肪(Fat-Libraries)应用程序的图书馆依赖关系度量指标是其库依赖关系图的边数。 该图包含应用程序的所有库。 (要在合成视图中查看相应的graphics,必须启用结构浏览器的显示库切换。)
胖包裹依赖关系(胖包)应用程序的胖包裹依赖关系度量指标是其扁平包裹依赖关系图的边数。 该图包含应用程序的所有包。 (要在“合成视图”中查看相应的graphics,必须启用“结构浏览器的平面软件包”切换,并且必须禁用“显示库”切换。
库的Flat Package Dependencies指标是其扁平包依赖关系图的边数。 此图包含库的所有包。 (要在合成视图中查看相应的graphics,必须启用结构浏览器的平面软件包和显示库切换。)
顶级类依赖关系(胖单位)应用程序或库的顶级类依赖关系度量标准是其单位依赖关系图的边数。 此图包含应用程序或库的所有顶级类。 (对于合理的应用程序来说,它太大而不能被可视化,因此不能显示在合成视图中,只能显示包的依赖关系图。
度量标准可能有助于确定项目中的改进或降级,并且可以肯定会发现风格和惯例违规,但是不能替代同行代码审查。 没有他们,你不可能知道你的代码的质量。
噢…而且这个假设至less有一个代码审查的参与者有一个线索。
我同意你的观点,代码指标不应该取代代码审查,但我相信他们应该补充代码审查。 我认为这回到老话说“你不能改善你无法衡量的东西”。 代码度量可以为开发团队提供可量化的“代码气味”或可能需要进一步调查的模式。 在大多数静态分析工具中捕获的度量标准通常是在我们领域的短期历史研究过程中确定的具有重要意义的度量标准。
度量标准不是代码审查的替代品,但它们要便宜得多。 他们比任何东西都是一个指标。
答案的一部分是,一些代码度量可以给你一个非常快速的,初步的刺答案,这个代码是什么样的?
即使是“代码行”,也可以让您了解您正在查看的代码库的大小。
正如另一个答案中提到的那样,指标的趋势给你提供了最多的信息。
他们的指标并不特别有趣。 这就是你对他们所做的事情。
例如,如果您正在测量每行代码的评论数量,那么您认为哪个值是一个好的值? 谁知道? 或者更重要的是,每个人都有自己的看法。
现在,如果您收集足够的信息来将每行代码的注释数量与解决错误所花费的时间或发现的归因于编码的错误数量关联起来,那么您可以开始find一个经验有用的数字。
在软件中使用度量标准和在其他任何过程中使用任何其他性能度量之间没有区别 – 首先您测量,然后分析,然后改进过程。 如果你所做的只是在测量,那么你正在浪费你的时间。
编辑:回应史蒂文答Lowe的意见 – 这是绝对正确的。 在任何数据分析中,必须仔细区分因果关系和单纯的相关性。 而且基于适宜性的度量标准的select是重要的。 尝试衡量咖啡的消费量并确定代码质量是毫无意义的(尽pipe我确信有人尝试过;-))
但是,在find关系之前(因果关系),你必须得到这些数据。
要收集的数据的select取决于您希望validation或改进的过程。 例如,如果您试图分析代码审查过程的成功(使用您自己的“成功”定义,减less错误,减less编码错误,缩短周转时间等等),那么您可以select度量在审查代码中的错误率和错误率。
所以在你收集数据之前,你必须知道你想要做什么。 如果指标是手段,那末端是什么?
我不认为度量的细微变化是有意义的:复杂度为20的函数不一定比复杂度为30的函数更清晰。但是值得运行的度量值寻找巨大的差异是值得的。
有一次,我正在调查几十个项目,其中一个项目的复杂度最大值大约是6000,而其他项目的值都在100或更小。 那像棒球棒一样打我的头。 显然,这个项目正在进行一些不寻常的事情,而且可能很糟糕。
我们是程序员。 我们喜欢数字。
另外,你打算做什么,不要描述代码库的大小,因为“代码行数是不相关的”?
150个代码库和1.5亿个代码库之间肯定有区别,这是一个愚蠢的例子。 而且这不是一个难以获得的数字。