65.9K
CodeProject 正在变化。 阅读更多。
Home

计算代码行数

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2016年10月4日

CPOL

5分钟阅读

viewsIcon

9727

您的项目文件中平均有多少行代码?是的,但平均值是多少?

引言

在监控代码库的健康状况时,一个“坏味道”是文件大小。过大的文件大小可能表明,例如,违反了SOLID原则中的单一职责原则。因此,跟踪项目层级中最大文件大小是有诱惑力的。

不幸的是,这种策略必然会找出异常值。文件可能臃肿的原因是它包含样板代码,在这种情况下,跟踪此信息对开发人员没有用。文件大小小可能也值得关注。例如,90年代初学习C语言的教材展示了仅用一行巧妙的代码就能实现的奇迹。不幸的是,应该使用的“巧妙”的所有同义词都太粗鲁了,无法在此重复。

那么,如何跟踪文件中(或类等)代码行数的有意义的统计数据呢?通过使用统计数据!特别是通过报告置信区间,即变量在特定概率下预计会落在哪两个值之间的范围。例如,天气预报员可能会说,明天降雨量有90%的几率在2厘米到10厘米之间。

拟合概率分布

要计算置信区间,需要对概率分布下的面积进行积分。众所周知,文件中的代码行数(LOC)是一个非负整数,并且预计LOC的值可能被某些文件共享,并且在项目中找到的不同LOC值之间,存在没有文件具备的中间值。因此,可以推断需要一个在半无限实线上连续的概率分布。

通过检查一些数据,事情会容易得多,例如Linux内核4.6的ARM构建中的文件。它包含19912871 行(只是基本计数,未过滤空行/注释),分布在42186 个文件中,平均每文件472 行。最大的文件包含33510 行。将区间从034000 分成100 个桶,并计算分配到每个桶的文件数量(第一个桶包含介于1340 行之间的所有文件计数)。这构建了以下直方图

Uniform bins

由于它非常陡峭,因此很难拟合曲线,是时候重新思考了。请注意,它看起来像指数衰减,通常行数会四舍五入到最接近的10的幂。因此,从行数的基数10对数构建一个直方图,得到以下结果

log10(LOC) histogram

通过取对数,半无限实线被映射到无限实线,[0, +inf) => (-inf, +inf),因此映射到不同类别的概率分布。直方图看起来非常像正态(也称为高斯或钟形曲线)分布。将原始随机变量表示为X,将新变量表示为Y = log(X),然后定义均值为Y_bar = sum(Y) / sum(1),方差为s^2 = sum( (Y -Y_bar)^2 ) / (sum(1) - 1),其中求和是针对文件的。对于正态分布,90%的置信区间可以计算为Y_bar +/- 1.645 * s,然后取指数返回到X = 10^Y

示例数据的具体数字是

  • Y_bar = 2.260263
  • s = 0.635845
  • Y_bar +/- 1.645 * s = [1.214297, 3.306228]
  • 10^Y_bar = 182
  • [10^1.214297, 10^3.306228] = [16, 2024]

因此,数字表明平均文件大小为182行,并且预计文件大小将在16到2024行之间变化。实际比较表明,91%的文件在此区间内。

软件实现

该方法已在我软件架构工具 DeepEnds 的HTML报告中实现(源代码)。这允许在一些示例项目上运行以评估其有用性。查看Visual C++项目层级的一个级别(部分指的是过滤器)

SLOC        
Sum Lower 预期效果 Upper 最大值  
5060 6 28 130 469 FEA
3493 7 28 105 469 FEA\Core
472 9 33 114 93 FEA\Equations
522 6 36 195 189 FEA\FileIO
48 17 23 31 27 FEA\LinearSystem
237 12 47 178 101 FEA\Mesh
281 12 99 774 240 FEA\Solver

在顶层,数字看起来不错,但是可以看到FEA\Solver的上限与最大值的比率大于3。检查该部分,可以看到它仅包含两个叶节点。

依赖 SLOC
FEA\Solver\Solver.cpp 240
FEA\Solver\Solver.h 41

因此,可以看到巨大的差异是由于比较的文件幅度预计不同所致。

切换到C#项目并使用Roslyn进行解析(部分指的是命名空间)

SLOC        
Sum Lower 预期效果 Upper 最大值  
1751 5 25 118 189 DeepEnds
119 37 58 92 71 DeepEnds.Console
712 4 23 122 189 DeepEnds.Core
68 4 26 143 55 DeepEnds.Core.Complex
94 1 12 116 63 DeepEnds.Core.Dependent
71 6 19 64 44 DeepEnds.Core.Linked
112 3 26 181 59 DeepEnds.Cpp
284 5 23 104 132 DeepEnds.CSharp
253 6 28 126 132 DeepEnds.CSharp.ParseTree
61 61 61 61 61 DeepEnds.Decompile
65 65 65 65 65 DeepEnds.DGML
106 3 18 103 60 DeepEnds.GUI
292 5 23 109 136 DeepEnds.VBasic
261 6 29 133 136 DeepEnds.VBasic.ParseTree

可以看到,在较低级别,上限/最大值的比率要好得多,但仍然不尽人意。

结论

已证明对数正态概率分布适合对项目中文件/类之间代码行数的分布进行建模。置信区间的有用性仅在层级的较高层级适用。

历史

  • 2016/10/04: 首次发布
© . All rights reserved.