LOC计数应该包括测试和注释吗?

16

虽然LOC(代码行数)是衡量代码复杂性的一个有问题的指标,但它是最受欢迎的指标之一。如果小心使用,可以提供至少相对复杂性的粗略估计。(例如,如果一个程序是10KLOC,而另一个程序是100KLOC,两者都用同样的语言编写,由大致相同素质的团队编写,则第二个程序几乎肯定更为复杂。)

在计算代码行数时,您喜欢计算注释吗?那测试呢?

我见过不同的方法。例如,cloc和sloccount等工具允许包含或排除注释。但其他人则认为注释是代码及其复杂性的一部分。

对于单元测试,也存在同样的困境,因为有时候单元测试的行数甚至会达到被测试代码的规模,甚至超过它。

我观察到的做法各不相同,从仅计算“操作”的非注释非空行,到计算“已测试、已注释代码的XXX行”,这更像是在项目中的所有代码文件上运行“wc -l”的结果。

您个人的偏好是什么?为什么?

8个回答

22
一位智者曾告诉我:“在管理程序员方面,你会得到你所衡量的结果。”
如果你将程序员的表现以代码行数作为评估标准,你可能会得到大量的代码行数。
如果你以他们关闭的错误数量作为评估标准,惊人的是你会得到很多已修复的错误。
如果你根据添加的功能来评估他们,你会得到很多新功能。
如果你以圆形复杂度来评估他们,你会得到非常简单的函数。
由于当前代码库的主要问题之一是它们增长速度非常快,而且一旦它们增长,就很难更改,因此我避免使用代码行数作为衡量标准,因为这会导致错误的基本行为。
话虽如此,如果你必须使用代码行数作为衡量标准,请排除注释和测试代码,并要求采用一致的编码风格。
但是,如果您真的想要衡量“代码大小”,只需将代码库进行tar.gz压缩。这往往比计算行数更好地估计了“内容”,因为行数易受不同编程风格的影响。

2
如果您在列表中添加“如果您按客户满意度评分,...”,我想知道结论会是什么。 - Black
5
如果你按照客户满意度来评价它们,你会得到非常大的费用报告。 ;) - Edward Kmett

11

测试和注释也必须得到维护。如果您要将代码行数(LOC)作为指标(我假设您不会听从我的建议),则应该提供所有三个数据(真实代码行数、注释和测试)。

最重要的(并且希望是显而易见的)是保持一致性。不要只报告一个项目的真实代码行数,另一个项目却将所有三个数据合并。找到或创建一个可自动化此过程并生成报告的工具。

Lines of Code:       75,000
Lines of Comments:   10,000
Lines of Tests:      15,000
                  ---------
Total:              100,000

这样你就可以确保它会:

  1. 完成。
  2. 每次都以相同的方式完成。

1
+1 维护推理。我个人从不使用 LoC 作为指标,但每隔一个月或两个月,管理层都会要求统计项目的 LoC 数量。包括注释和测试的优势在于可以简化我的计数流程,只需使用 PowerShell 中的一行命令即可完成。 :) - Greg D
我同意。不管怎样,测试必须尽早编写。 - Spartan

2

我个人认为,LOC指标本身并不像其他一些代码指标那样有用。

NDepend 将为您提供LOC指标,但还将为您提供许多其他指标,例如圆形复杂度。这里不列出所有指标,而是给出了链接以供参考。

还有一个免费的CodeMetric插件适用于Reflector


1

我不会直接回答你的问题,因为我讨厌代码行数这个指标。无论你想要衡量什么,很难找到比LOC更糟糕的指标;几乎任何其他你能想到的指标都会更好。

特别是,你似乎想要衡量你的代码的复杂性。总体圈复杂度(也称为麦卡贝复杂度)是更好的指标。

具有高圈复杂度的程序是你需要关注的程序。这些程序很难测试,充满了错误和难以维护。

有许多工具可以测量这种复杂性。在你喜欢的编程语言上进行快速的谷歌搜索,就会找到数十种执行此类复杂性分析的工具。


1

代码行数的确意味着这个:不计算注释或空白行。同时,为了让它能与其他源代码进行比较(无论这个度量标准是否有用),你需要至少具有相似的编码风格:

for (int i = 0; i < list.count; i++)
{
    // do some stuff
}

for (int i = 0; i < list.count; i++){
    // do some stuff
}

第二个版本与第一个版本完全相同,但代码行数少了一行。当你有很多嵌套的循环时,这可以节省不少空间。这就是为什么像function points这样的指标被发明的原因。


这种类型分析的大多数工具都是测量逻辑代码行(LLOC),这将对上述两个代码块计数相同。 - Daniel Papasian

0

文章摘录:如何计算代码行数(LOC)?与工具NDepend相关,该工具计算.NET程序的逻辑代码行数


如何计算代码行数(LOC)?

您是否计算方法签名声明?您是否计算只有括号的行?当单个方法调用由于参数数量较多而写在多行上时,您是否会计算几行?您是否计算“命名空间”和“using namespace”声明?您是否计算接口和抽象方法声明?在声明时分配字段时,您是否会计算?您是否计算空白行?

根据每个开发者的编码风格以及所选择的语言(C#,VB.NET等),通过测量LOC可能会出现显着差异。

从解析源文件中测量LOC似乎是一个复杂的问题。幸运的是,存在一种聪明的方法可以精确测量所谓的逻辑LOC。逻辑LOC相对于物理LOC(从解析源文件推断出的LOC)具有两个重要优点:

  • 编码风格不会影响逻辑LOC。例如,因为参数数量较多而将方法调用产生在多行上,LOC不会改变。
  • 逻辑LOC与语言无关。使用不同语言编写的程序集得到的值是可比较并且可以求和的。
在.NET世界中,逻辑行数(LOC)可以从PDB文件中计算出来,这些文件由调试器用于将IL代码与源代码链接。 NDepend工具通过以下方式计算方法的逻辑LOC:它等于在PDB文件中找到的序列点数。 序列点用于标记IL代码中对应于原始源中特定位置的位置。 更多关于序列点的信息请参见此处。 请注意,不考虑与C#大括号“{”和“}”对应的序列点。
显然,类型的LOC是其方法的LOC之和,名称空间的LOC是其类型的LOC之和,程序集的LOC是其名称空间的LOC之和,应用程序的LOC是其程序集的LOC之和。以下是一些观察结果:
  • 接口、抽象方法和枚举的代码行数为0。只有实际执行的具体代码才会在计算代码行数时被考虑。
  • 命名空间、类型、字段和方法声明不被视为代码行数,因为它们没有相应的序列点。
  • 当C#或VB.NET编译器面对内联实例字段初始化时,它会为每个实例构造函数生成一个序列点(对于内联静态字段初始化和静态构造函数也适用此规则)。
  • 从匿名方法计算出的代码行数不会干扰其外部声明方法的代码行数。
  • C#和VB.NET中NbILInstructions和LOC之间的总比率通常约为7。

0

我们只使用代码行数作为一项指标 - 一个函数应该包含足够少的代码行,以便在不滚动屏幕的情况下阅读。如果函数超过这个大小,即使它们的圆形复杂度非常低,通常也很难阅读。对于此用途,我们会计算空格和注释。

在重构期间,了解您删除了多少行代码也是很好的 - 在这里,您只需要计算实际的代码行,而不是不利于可读性的空格和无用的注释(这些无法自动化)。

最后,免责声明 - 聪明地使用指标。指标的好处是帮助回答“哪部分代码最需要重构”或“最新检入的代码审查有多紧急”的问题 - 具有50个圆形复杂度的1000行函数就像闪烁的霓虹灯标志着“现在重构我”。指标的不良用途是“程序员X的生产力如何”或“我的软件有多复杂”。


0

这取决于您使用LOC的目的。

作为复杂度度量-不太适用。也许100KLOC大部分是从简单表格生成的代码,而10KLOC包含5KLOC的正则表达式。

然而,我认为每行代码都与运行成本相关联。只要程序存在,您就需要为每行代码付费:在维护时需要阅读它,它可能包含需要修复的错误,它会增加编译时间、从源代码控制和备份时间,更改或删除它之前,您可能需要找出是否有人依赖它等等。每行代码的平均成本可能是纳米便士每天,但这是一些会累积的东西。

KLOC可以是项目需要多少基础设施的第一指标。在这种情况下,我会包括注释和测试-尽管注释行的运行成本远低于第二个项目中的正则表达式之一。

[编辑] [持有类似代码大小观点的人] 1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接