我最近在SO上看到了一些与“代码指标”相关的问题,不得不想知道这些魅力是什么?以下是一些最近的例子:
在我看来,没有指标可以替代代码审查,但是:
但是我想不出一个单独的指标本身总是表示“好”或“坏”代码 - 测量无法看到的东西总是有例外和原因。
从我忽略的代码指标中获得了一些神奇的洞察力吗?懒惰的程序员/经理是否在寻找不读代码的借口?人们是否提供了巨大的遗留代码库并寻找起点?发生了什么事?
注意:我已经在答案和评论中询问了一些关于特定线程的问题并且没有得到回复,所以我认为我应该问整个社区,因为我可能错过了一些东西。运行一个指标批处理作业并不是真的必须再次读取其他人的代码(或我自己的代码)会很好,我只是觉得它不实用!
编辑:我对大多数(如果不是所有)正在讨论的指标都很熟悉,我只是没有把它们视为孤立或任意质量标准。
答案 0 :(得分:81)
这个帖子中的答案有点奇怪,因为他们说:
1 / Metrics不适用于一个人口,但适用于三个:
当然,所有这三个人群都可以观察和分析所有这些指标,但每种指标都可以被每个特定群体更好地使用。
2 / Metrics,它们本身代表代码的 快照 ,这意味着......什么都没有!
这些指标的组合,以及可能表示“好”或“坏”代码的那些不同分析级别的组合,但更重要的是, 这些指标的趋势 这很重要。
这些指标的重复将带来真正的附加价值,因为它们将帮助业务经理/项目负责人/开发人员 优先排序 < / strong>在不同的可能代码修复中
换句话说,您关于“指标的魅力”的问题可能指的是:
之间的区别因此,例如,具有9的圈复杂度的函数可以被定义为“漂亮”,而不是42的圈复杂度的一个长卷积函数。
但是,如果:
所以,总结一下:
单个指标本身始终指示[...]
:不多,除了代码可能更“漂亮”,这本身并不意味着很多......
从我忽略的代码指标中获得了一些神奇的洞察力吗?
只有指标的组合和趋势才能给出真正的“神奇见解”。
答案 1 :(得分:21)
我有一个项目,我作为一个人的工作在一个月前测量了圈复杂度。这是我第一次接触这些指标。
我得到的第一份报告令人震惊。几乎所有的功能都没有通过测试,即使是(imho)也非常简单。我通过将逻辑子任务移动到子例程中来解决复杂问题,即使它们只被调用一次。
对于另一半例程,我作为程序员的骄傲被踢了,我试图以他们做同样的方式重写它们,只是更简单,更易读。这很有效,而且我能够最大限度地降低客户的yclomatic复杂性门槛。
最后,我几乎总能找到更好的解决方案和更清晰的代码。性能没有受到这种影响(相信我 - 我对此很偏执,我经常检查编译器输出的反汇编)。
我认为,如果您将指标用作改进代码的理由/动机,那么指标就是一件好事。知道何时停止并要求获得指标违规授权是非常重要的。
指标是指导和帮助,而不是目的本身。
答案 2 :(得分:14)
我用过的最好的指标是C.R.A.P.得分了。 http://www.artima.com/weblogs/viewpost.jsp?thread=215899
基本上,它是一种将加权圈复杂度与自动测试覆盖率进行比较的算法。算法如下所示:CRAP(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m)
其中comp(m)是方法m的圈复杂度,cov(m)是自动化测试提供的测试代码覆盖率。
上述文章的作者(请阅读它......非常值得您的时间)建议最大C.R.A.P.分数为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.
正如您很快看到的那样,该指标奖励编写不复杂的代码以及良好的测试覆盖率(如果您正在编写单元测试,而您应该,并且不测量覆盖率......好吧,您可能会喜欢随地吐痰在风中也是如此)。 ; - )
对于我的大多数开发团队,我都非常努力地获得C.R.A.P.得分低于8,但如果他们有正当理由证明增加的复杂性是可以接受的,只要他们用足够的测试覆盖了复杂性。 (编写复杂的代码总是很难测试......对这个指标有一种隐藏的好处)。
大多数人发现很难编写能够通过C.R.A.P的代码。得分了。但随着时间的推移,他们编写了更好的代码,代码更少的问题,代码更容易调试。在任何指标中,这是最少关注和最大利益的指标。
答案 3 :(得分:9)
对我而言,识别错误代码的最重要指标是圈复杂度。我项目中的几乎所有方法都低于CC 10,并且在CC超过30的传统方法中总是会发现错误。 高CC通常表示:
答案 4 :(得分:9)
良好的代码审查不能替代一个好的静态分析工具,它当然不能代替一套好的单元测试,如果没有一套验收测试,现在单元测试是不行的...... < / p>
代码指标是放入工具箱的另一个工具,它们本身不是一个解决方案,它们只是一个适当使用的工具(当然还有所有其他工具!)。
答案 5 :(得分:6)
人们被理解为理解和描述代码的机制方法。如果是真的,请考虑效率和生产力的后果!
我同意“代码优点”的指标与“好散文”的指标一样合理。然而,这并不意味着指标没用,只是可能被滥用。
例如,某些指标的极端值指出可能存在的问题。一个1000行长的方法可能不可维护。具有零单元测试代码覆盖率的代码可能具有更多错误,类似的代码具有大量测试。在发布之前添加到项目中的代码的大幅跳跃不是第三方库可能引起额外关注。
我认为如果我们使用指标作为建议 - 一个红旗 - 也许它们可能有用。问题在于人们开始用SLOC来衡量生产率,或者用测试来评估生产线的质量。
答案 6 :(得分:6)
我的高度主观意见是,代码指标表达了不可抗拒的制度迷恋,能够量化本质上无法量化的东西。
在某种程度上,至少在心理上是有道理的 - 你怎么能对你无法评估或理解的事情做出决定?当然,最终,你不能评估质量,除非你对这个主题有所了解(并且至少和你想要评估的那样一样好),或者问一个知识渊博的人,这当然只是把问题归咎于一步。
从这个意义上讲,也许一个合理的类比就是通过SAT分数来评估大学入学者,这是不公平的,并且错过了各种微妙之处,但如果你需要量化,你必须做点什么。
不是说我认为这是一个很好的衡量标准,只是我能看出它的机构不可抗拒性。并且,正如您所指出的,可能有一些合理的指标(大量500多行方法,高复杂性 - 可能很糟糕)。不过,我从来没有去过这个地方。
答案 7 :(得分:6)
我相信有一个代码指标。
我正在研究一个大系统。当我遇到一个新的要求时,我开始编写代码。当我完成并解决了错误后,我将其检入版本控制系统。该系统做了差异,并计算了我所做的所有更改。
该数字越小越好。
答案 8 :(得分:5)
以下是stan4j(http://stan4j.com/)的一些复杂度指标。
eclipse类结构分析工具。
我喜欢这个工具和指标。我将指标视为统计数据,指标,警告消息。有时由于某些方法或某些类确实有一些复杂的逻辑使它们变得复杂,应该做的是密切关注它们, 检查它们以查看是否需要重构它们或仔细检查它们,因为它们通常容易出错。我也使用它作为分析工具来学习源代码,因为我喜欢从复杂到简单的学习。实际上它还包括一些其他指标,如Robert C. Martin Metrics,Chidamber&amp; Kemerer Metrics,Count Metrics 但我最喜欢这个
复杂度指标
圈养复杂度指标
Cyclomatic Complexity(CC) 方法的圈复杂度是方法的控制流图中的决策点数增加1。决策点出现在if / for / while语句,case / catch子句和类似的源代码元素中,其中控制流不仅仅是线性的。由单个(源代码)语句引入的(字节代码)决策点的数量可以变化,这取决于例如关于布尔表达式的复杂性。方法的圈复杂度值越高,测试方法控制流图的所有分支所需的测试用例就越多。
平均周期复杂度 应用程序,库,包树或包的所有方法的Cyclomatic Complexity度量标准的平均值。
Fat Metrics 工件的Fat度量是工件的适当依赖关系图中的边数。依赖关系图类型取决于度量标准变量和所选工件:
<强>脂肪强> 应用程序,库或包树的Fat度量标准是其子树依赖关系图的边数。此图包含包树层次结构中的所有工件子项,因此还包括叶包。 (要在Composition视图中查看相应的图形,必须禁用Structure Explorer的Flat Packages切换。如果所选工件是库,则必须启用Show Libraries切换,否则必须禁用它。)
包的Fat度量是其单位依赖关系图的边数。此图包含包的所有顶级类。
类的Fat度量是其成员图的边数。此图包含该类的所有字段,方法和成员类。 (此图表和Fat值仅在代码分析使用Level of Detail Member而不是Class执行时才可用。)
图书馆依赖的脂肪(脂肪 - 图书馆) 应用程序的Fat for Library Dependencies度量标准是其库依赖关系图的边数。该图包含应用程序的所有库。 (要在“合成视图”中查看相应的图形,必须启用Structure Explorer的“显示库”切换。)
扁平包依赖的胖(胖 - 包) 应用程序的Fat for Flat Package Dependencies度量标准是其扁平包依赖关系图的边数。此图包含应用程序的所有包。 (要在Composition视图中查看相应的图形,必须启用Structure Explorer的Flat Packages切换,并且必须禁用Show Libraries切换。)
库的Fat for Flat Package Dependencies度量标准是其扁平包依赖关系图的边数。此图包含库的所有包。 (要在Composition视图中查看相应的图形,必须启用Structure Explorer的Flat Packages和Show Libraries切换。)
最高级别依赖性(脂肪 - 单位)的脂肪 应用程序或库的顶级类依赖性度量标准是其单元依赖关系图的边数。此图包含应用程序或库的所有顶级类。 (对于合理的应用程序,它太大而无法可视化,因此无法在组合视图中显示。单元依赖关系图只能显示在包中。)
答案 9 :(得分:5)
测量仅在以下情况下有用:
一般而言,任何不适合的指标都会受到团队优化的影响。你想测量代码行吗?通过天哪,看看他们能写多少!你想要测量代码覆盖率,请看我覆盖那段代码!
我认为指标对于识别趋势非常有用,事实上,我已经看到了一些有用的指标,例如构建中断时的绘图,代码流失(整个项目中代码行数的变化)和其他事情。但如果团队没有提出他们,或者他们不同意或理解他们,那么你很可能会受到伤害。
答案 10 :(得分:5)
度量标准和自动化测试并不能代替完整的代码审查。
他们只是加快了速度。使用自动检查器,您可以轻松查看您忘记遵循的约定,使用指定的包和方法等。您可以在不使用其他人的情况下查看可以修复的内容。
管理人员也喜欢衡量他们,因为他们觉得他们已经获得了生产力的确切数字(尽管通常情况并非如此),他们应该能够更好地兼顾人员。
答案 11 :(得分:2)
指标不能代替代码审查,但它们便宜得多。它们比任何事情都更重要。
答案 12 :(得分:2)
答案的一部分是,一些代码指标可以为您提供一个非常快速的初步答案:这个代码是什么样的?
即使是“代码行”也可以让您了解您正在查看的代码库的大小。
正如另一个答案中所提到的,指标的趋势为您提供了最多的信息。
答案 13 :(得分:2)
我同意您的观点,代码指标不应取代代码审核,但我相信它们应该补充代码审核。我认为它回到了一句古老的说法:“你无法改进你无法衡量的东西。”代码度量可以为开发团队提供可量化的“代码味道”或可能需要进一步调查的模式。在大多数静态分析工具中捕获的指标通常是在我们的领域的短期历史中已经确定的具有重要意义的指标。
答案 14 :(得分:2)
自己的指标并不是特别有趣。这就是你用它们做的事情。
例如,如果您测量每行代码的注释数量,您会认为什么是好的值?谁知道?或许更重要的是,每个人都有自己的观点。
现在,如果您收集足够的信息,以便能够将每行代码的注释数量与解决错误所花费的时间或编码所发现的错误数量相关联,那么您可能会开始找到一个经验上有用的数字。
在软件中使用指标和在任何其他流程上使用任何其他性能指标之间没有区别 - 首先测量,然后分析,然后改进流程。如果你所做的只是测量,那你就是在浪费时间。
编辑:回应Steven A. Lowe的评论 - 这是绝对正确的。在任何数据分析中,必须小心区分因果关系和单纯的相关性。根据适用性选择指标很重要。尝试测量咖啡消费量并归因于代码质量是没有意义的(虽然我确信有些人已尝试过;-))
但在找到关系(因果与否)之前,您必须拥有数据。
要收集的数据的选择取决于您希望验证或改进的过程。例如,如果您试图分析代码审查程序的成功(使用您自己的“成功”定义,减少错误或减少编码错误,或缩短周转时间等),那么您选择衡量指标已审核代码中的错误率和错误率。
因此,在收集数据之前,您必须知道要使用它做什么。如果指标是手段,那么结束是什么?
答案 15 :(得分:2)
度量标准可能对确定项目的改进或降级很有用,并且当然可以找到违反样式和约定的行为,但无法替代进行同行代码审查。没有它们,你不可能知道代码的质量。
哦......这假设您的代码审核中至少有一位参与者有线索。
答案 16 :(得分:2)
我不认为指标的微小变化是有意义的:复杂度为20的函数不一定比复杂度为30的函数更清晰。但值得运行指标以寻找较大的差异。
有一次,我正在调查几十个项目,其中一个项目的最大复杂度值约为6,000,而其他每个项目的值都在100左右或更低。这让我像棒球棒一样击中头部。显然,这个项目正在发生一些不寻常的,可能是不好的事情。
答案 17 :(得分:1)
我们是程序员。我们喜欢数字。
另外,你打算做什么,不描述代码库的大小,因为“代码行指标不相关”?
150行的代码库和1.5亿的代码库之间肯定存在差异,这是一个愚蠢的例子。这不是一个难以理解的数字。