7

每个现代源代码控制系统都可以切分程序的历史。有许多工具可以静态和动态地分析代码。什么样的数学公式可以让我将文件中的活动量与该软件的部署数量相结合?我们发现即使一个程序完成了所有的单元测试,它也需要比我们在升级时预期的更多的工作。这种类型的测量应该是可能的,但是坐下来思考它的单位让我难住了。

更新:如果某些东西被发送到测试机器,我可以看到它的标记不那么烂。如果某些东西被发送到所有测试盒,我可以看到它得到一个新的标记。如果有东西投入生产,我可以点头并降低它的bitrot分数。如果它的文件中有很多活动并且它永远不会被发送到任何地方,我就会把它搞砸。不要专注于代码假设我需要的任何数据都在手边。

什么样的提交分析(提交评论(如下所述)或提交之间的时间)是适用的公平数据?

更新: 我认为维度分析可能只是基于年龄。相对来说就困难一些了。旧代码很烂。每行代码的平均年龄仍然只是时间的度量。较大的源模块是否比更小、更复杂的源模块腐烂得更快?

更新代码覆盖率以行为单位。根据定义,经常执行的代码必须比从未执行的代码更糟糕。要准确测量 bitrot,您需要覆盖分析来充当阻尼器。

4

11 回答 11

4

非常有趣的思路!

首先,什么bitrot?维基百科上的Software Rot文章收集了几点:

  • 环境变化:运行时的变化
  • 未使用的代码:使用模式的变化
  • 很少更新的代码:通过维护更改
  • 重构:一种阻止比特腐烂的方法

根据摩尔定律delta(CPU)/delta(t)每 18 到 24 个月是一个常数因子 2。由于环境包含的不仅仅是 CPU,我认为这只是环境实际变化的一个非常弱的下限。单位:OPS/$/s,每秒每美元的操作数随时间的变化

delta(users)/delta(t)很难量化,但从新闻中“知识时代”一词的出现频率来看,我想说用户的期望也呈指数级增长。通过观察$/flops基础经济的发展告诉我们,供给增长快于需求,摩尔定律成为用户变化的上限。我将使用功能点(“信息系统向用户提供的业务功能量”)作为需求量度。单位:FP/s,所需功能点随时间的变化

delta(maintenance)/delta(t)完全取决于组织,通常在发布前、快速修复和集成重大更改时非常高。随着时间的推移,对各种度量(如SLOC圈复杂度或已实现的功能点)的更改可以用作此处的替身。如果可能的话,另一种可能性是票务系统中的错误流失。随着时间的推移,我将继续使用已实现的功能点。单位 = FP/s,实现的功能点随时间的变化

delta(refactoring)/delta(t)可以衡量为实施新功能所花费的时间。单位 = 1,随着时间的推移重构所花费的时间

所以bitrot会是

             d(env)     d(users)     d(maint)        d(t)
bitrot(t) = -------- * ---------- * ---------- * ----------------
              d(t)        d(t)        d(t)        d(refactoring)

             d(env) * d(users) * d(maint)
          = ------------------------------
                d(t)² * d(refactoring)

与一个组合单位OPS/$/s * FP/s * FP/s = (OPS*FP²) / ($*s³)

这当然只是维基百科文章已经说过的非常强制的伪数学符号:bitrot 源于环境的变化、用户需求的变化和代码的变化,而通过花时间重构来缓解它。每个组织都必须自己决定如何衡量这些变化,我只给出非常笼统的界限。

于 2009-04-03T22:45:05.943 回答
2

我不同意 Charlie 的观点:对源代码的轻微重构会导致非常大的汉明距离,并且不能很好地衡量代码在逻辑上被修改的程度。

我会考虑查看提交评论的长度。对于给定的程序员,相对较长的提交注释通常表明他们对代码进行了重大更改。

于 2009-04-03T22:43:42.327 回答
2

最简单的答案怎么样?

foreach (file in source control){
  file.RotLevel = (Time.Now - file.LastTestedOrDeployed)
}

如果一个文件很长时间没有被部署(生产或测试机器),它可能与“现实”不同步。环境可能已经改变,即使文件没有改变,它也可能不再起作用。所以在我看来,这是一个简单而准确的公式。为什么让它比这更复杂?涉及的变化数量似乎只会增加不确定性。如果一个文件最近被修改过,这是否意味着它已经更新以反映环境的变化(这使得它“不那么烂”),或者添加了新功能(增加了出错的风险,因此使它成为“更烂”)?对文件的修改可能意味着任何事情。

我能想到的唯一明确的因素是“自从我们上次验证文件有效以来已经多久了?”

于 2009-04-03T23:56:19.093 回答
1

我想起了基于证据的调度。提出一组合理的指标来指示比特腐烂(它的实际价值和特定变化减少了多少)。然后根据以后花费的时间确定它们的准确性。为此提出数字和规则可能很复杂。

于 2009-04-13T17:18:47.473 回答
1

显而易见的答案是否定的。BItrot 没有任何可接受的尺寸。

于 2009-04-13T20:40:25.180 回答
0

单元测试数量与代码总行数成反比?

于 2009-04-03T21:46:11.810 回答
0

考虑两种可能的措施:编辑差异,如汉明或瓦格纳距离;和信息论熵。

于 2009-04-03T21:50:26.930 回答
0

如果您真的有兴趣深入研究,可以进行一些研究。不久前,我正在研究一篇文章中的概念,该文章检查了组织结构对软件质量的影响。我最终将这些想法归档在我的脑后,但你可能会发现它很有启发性。

于 2009-04-07T17:03:31.360 回答
0

由于我们不关心有效的代码,我会查看对文件所做的更改数量(不是更改有多大,只是更改文件的频率)以及这些更改修复了多少错误加上针对文件记录的打开错误的数量。结果应该是一个文件越烂越大的数字。

经常更改(配置等)而不修复大文件的文件将不会显示,因为等式的错误部分会很低。具有大量未解决的错误的文件将显示,更改通常会导致新错误的文件也会显示。更改*错误修复数量应该会随着时间的推移而逐渐消失(因为我们不关心旧热点)。

于 2009-04-09T11:28:20.090 回答
0

我对代码覆盖率和单元测试的唯一问题是单元测试只测试它们最初设计用于测试的内容,并且根据定义,它们是代码并且容易出现困扰常规代码的相同功能性软件腐烂。(它们只对所写的内容有好处,过了一段时间,这还不够)

但是高质量的单元测试显然会提供一些保护。

所以这些是我软件腐烂的重要因素:

  1. 外部数据接口点数 (extDataIntfPts)
    • 数据质量/错误处理,单元测试(codeQuality)
    • 对 OS/VM 等底层实现的依赖。(osDep)
    • 插件等外部实现接口点的数量。(extIntfPts)
    • 代码的复杂性/简单的代码量(linesOfCode)

当系统在生产中运行时,随着它收集的数据集的增长,它会接触到更多种类的数据输入。根据定义,这将代码库暴露给更多的边缘情况和序列。

这可以通过数据处理、错误处理和单元测试的质量来缓解。

还有系统运行的底层环境的移动目标。缓和这种情况的一种方法是将应用程序放在 VM 中。

如果系统实现了插件,我可以看到随着更多插件的开发,代码库面临更大的失败机会。

复杂的代码!= 优雅的代码。如果它很优雅,它可能很简单。我在这里简单点说,代码越多,它经过良好测试的可能性就越小,但我想它可以被扭转。

所以,这是我的等式:

bitrot=((linesofcode/codeQuality)*(extDataInfPts+(osDep/change)+extIntfPts)*numberOfSecondsDeployed)

判断 codeQuality 可能会涉及单元测试中代码覆盖率的度量。您可以针对它运行静态分析程序以确定潜在的错误,这也可能会有所帮助。我的意思是,在某些时候,真的很难得分,因为多线程代码的权重应该比 POJO 重得多。是的,应该考虑重构,但前提是有软件腐烂的证据。

归根结底,这是一门伪科学。这是我对伪科学的贡献。

于 2009-04-13T17:56:22.080 回答
0

真正的比特腐烂(不是软件腐烂)具有物理存储量 * 时间的维度。

Bitrot 是由存储介质中的杂质放射性衰变引起的。

于 2009-04-20T04:22:04.207 回答