如何量化项目中存在的技术债务金额?


67

有谁知道是否有某种工具可以将某种代码基础的技术债务作为一种代码指标?如果不是,是否有人知道它的算法或启发式方法?

如果到目前为止这些东西都不存在,那么我将对如何开始使用这种东西感兴趣。也就是说,如何量化由方法,类,名称空间,程序集等引起的技术债务。

我对分析和评估C#代码库最感兴趣,但也请随时注意其他语言,尤其是在概念是语言超越的情况下。


12
技术债务来自决策,而不是代码。它是由于错误的管理选择而产生的。尚不清楚“方法,类,名称空间,程序集”本身是否包含技术债务。当有更好的选择时,它们代表责任。
S.Lott 2012年

7
我认为(在债务的隐喻中)经理可能是债务持有人,但是代码工件代表着债务估值并且可以量化。就是说,我同意经理们可能会做出诸如“因为我们没有时间而忘记单元测试”之类的决定,从而招致技术债务。但是,我当然认为您可以将一些数字作为启发式输入到各个代码元素中。这样想吧-如果管理层为未来做出一系列可怕的决定,但没有编写任何代码,那时候是否有债务?
埃里克·迪特里希

3
“那一刻有债务吗?” 债务确实需要积累,您是对的。但这不是代码。要做的是“完成”的工作量。规格,设计,代码,DBA工作,所有这些都必须重新设计。从软件工件(如代码的源代码行)测量债务类似于预测开发成本。
S.Lott 2012年

7
衡量技术债务非常困难,而且会使管理人员感到困惑。但是,我可以告诉您一个解决技术难题的好方法:便宜,美观且可以正常工作的原型,尤其是如果代码库围绕GUI进行。正如Joel在这里建议的那样:joelonsoftware.com/articles/fog0000000332.html,每天花一点时间清理事物。改变必须是积极的改进,而不是“ OMG,我们的技术债务=五花八门,并且它正以……天空在下降的速度呈指数增长。” 每天花一点时间在改善上,不会破坏正常工作。做朋友。
Job

6
@ZoranPavlovic您奇怪的,不请自来的错误困境缺少第三个选择:我想知道是否有任何工具可以量化技术债务。
埃里克·迪特里希

Answers:


38

技术债务只是一个抽象的想法,即在设计,构建,测试和维护系统的过程中,某些决策已经做出,使得产品变得更加难以测试和维护。承担更多的技术债务意味着继续开发系统将变得更加困难-您要么需要应对技术债务并为越来越多的时间分配本来就很简单的任务,要么需要投入资源(时间和金钱)。金钱)通过重构代码,改进测试等来减少技术债务。

有许多指标可能会给您一些有关代码质量的指示:

  • 代码覆盖率。有多种工具可以告诉您单元测试覆盖了函数,语句和行的百分比。您还可以将系统测试和验收测试映射回需求,以确定系统级测试覆盖的需求百分比。适当的覆盖范围取决于应用程序的性质。
  • 耦合内聚。表现出低耦合和高内聚性的代码通常更易于阅读,理解和测试。有一些代码分析工具可以报告给定系统中的耦合和内聚程度。
  • 循环复杂性是通过应用程序的唯一路径的数量。通常在方法/功能级别进行计数。圈复杂度与模块的可理解性和可测试性有关。较高的圈复杂度值不仅表明有人会在遵循该代码方面遇到更多麻烦,而且圈复杂度还表明实现覆盖范围所需的测试用例数。
  • Halstead的各种复杂性度量可洞悉代码的可读性。这些计算操作符和操作数来确定数量,难度和工作量。通常,这些信息可以表明某人拿起代码并理解它的难度有多大,例如在代码审查或代码库的新开发人员中。
  • 重复代码量。代码重复可能表明有可能重构方法。拥有重复的代码意味着有更多的行要引入一个错误,并且更有可能在多个地方存在相同的缺陷。如果在多个位置存在相同的业务逻辑,则很难更新系统以应对更改。

通常,静态分析工具将能够提醒您潜在的问题。当然,仅因为工具指示问题并不意味着存在问题-需要人工判断才能确定将来是否会出现问题。这些指标只是警告您可能是时候更仔细地查看系统或模块了。

但是,这些属性集中在代码上。它们不会轻易表明您的系统架构或设计中可能涉及各种质量属性的任何技术债务。


1
我目前使用NDepend(ndepend.com),CodeRush和VS代码度量标准来关注您提到的度量标准(Halstead度量标准除外,我将对其进行进一步研究)。我当时想我可能会使用这些指标的某种组合来尝试在给定的代码元素上添加某种数字,从而一眼就能大致看出正在进行的开发的成本。
Erik Dietrich '02

@ErikDietrich您也许可以,但我可能无法量化该值。关于度量工具告诉您的随时间变化的“执行摘要”样式的报告,可能会更合适。
Thomas Owens

2
我要添加到列表中的另一个简单指标是TODO / HACK / WTF的数量?代码库中的注释...
MaR 2012年

@Mar假定您正确使用了这些,而不是为了自己的利益而赌博。需要一些额外的时间来清理代码库,只需在不适当的地方添加这些注释即可。不在乎代码库,只需将其从应有的位置删除即可。注释可以撒谎,代码不能撒谎。
汤玛斯·欧文斯

1
@Thomas Owens:同意,但是几乎任何度量标准都可以被欺骗。如果正确,诚实地使用“ TODO度量标准”,则可以廉价查看实际缺少或应更改的代码(=仅基于代码的度量标准不可见的债务)。
2012年

23

Sonar具有技术债务启发法以及对软件项目有用的其他几个功能。

它还支持多种语言。

SonarQube(以前的Sonar)是一个开源平台,用于持续检查代码质量...

  • 支持25种以上的语言:Java,C / C ++,C#,PHP,Flex,Groovy,JavaScript,Python,PL / SQL,COBOL等
  • SonarQube也用于Android开发中。
  • 提供有关重复代码,编码标准,单元测试,代码覆盖率,复杂代码,潜在错误,注释以及设计和体系结构的报告。
  • 时间机器和差分视图。
  • 全自动分析:与Maven,Ant,Gradle和连续集成工具(Atlassian Bamboo,Jenkins,Hudson等)集成。
  • 与Eclipse开发环境集成
  • 与外部工具集成:JIRA,Mantis,LDAP,Fortify等。
  • 通过使用插件可扩展。
  • 实施 SQALE方法以计算技术债务 ...

1
太好了,谢谢!我已经使用NDepend进行C#工作,但是我也做了一些Java工作,并且对那里的指标也很感兴趣。至少,这为我提供了Java功能,并且可以证明它是对NDepend的很好补充。
Erik Dietrich '02

太棒了,我们在我工作的地方使用Sonar,它确实做了一些很棒的事情,可让您深入了解代码库的状态。
罗伯特·格瑞纳

2
@ ErikDietrich,FYI Sonar也有一个C#插件
彼得Török

@ErikDietrich FYI现在有一个NDepend的插件声纳ndepend.com/docs/sonarqube-integration-ndepend
帕特里克Smacchia - NDepend的dev的

有开源替代品吗?
hellboy

5

我讨厌使用金融类比,但这似乎确实合适。当您为某物(任何种类的资产)定价时,它可以具有内在价值和外在价值。在这种情况下,现有代码具有内在价值,该内在价值将是与所述代码的相对质量相对应的数量,并且还将具有外在价值(从可以做的事情到代码的价值),而这些数量将是累加的。可以使用您用来对代码评分的任何方法将内在价值分解为借方和借方(好坏)(对于注释/可读性,+ 5;对于代码覆盖率,-10,等等)。

我当然不知道有什么工具可以量化这一点,如果您认为不同的“债务估值”策略的优点,您会在手上进行全新的讨论,但我同意马修(Matthew)的观点:使用您所使用的任何方法花费大量的工时来获取代码,从而获得尽可能好的代码的累积成本。

还有一些需要考虑的事情是,肯定存在一定的成本效益衡量标准,因为随着人们越来越接近“完美”,花费在代码库上的一个小时的价值很有可能呈指数下降,因此可能存在一个额外的优化问题。最大限度地发挥工作效用。


是的,减少边际收益的概念无疑是我提出和完善指标时要解决的问题。因此,不仅“这是我从业务角度重构此类的客观观点”,而且“这是我现在不打扰的理由”。
Erik Dietrich '02

5

在开发人员之间,技术债务的相当可靠的度量似乎是WTF /分钟

该“度量”的问题在于,通常很难在“外部”进行通信。

在向“外部人员”传达技术债务方面对我有用的衡量标准是成功交付所需的大量测试和错误修复工作(尤其是修复回归错误)。

提醒您一点:尽管这种方法功能强大,但最好还是先以良好的旧WTF /分钟进行仔细检查,然后再采取措施。事实是,这很麻烦:要获取数据,必须仔细跟踪时间并按照适当的类别准确地记录下来。

  • 相比于我在功能A的实施草案上花费14个小时,然后在烟雾测试上花费29个小时,然后在实施我发现的回归修复程序上花费11个小时,然后进行18个小时的质量检查测试所花费的时间,我要花3周的总时间来描述实现功能A要容易得多
     
    就绪的功能实现。之后,质量检查人员花了17个小时来测试初始候选版本。之后,我花了13个小时来分析QA为初始候选版本提交的错误,并花了3个小时来实施这些修复程序。之后,我花了11个小时进行烟雾测试,测试了我对最初的候选版本所做的更改。之后...

无论如何,根据我的经验,关于测试和错误修复工作的数据非常容易传达。

对于最新版本,我们花费了大约90%的时间来测试和修复回归错误。对于下一个版本,建议分配一些精力以使该值降低到60-70%。


另一个警告。高于90%的数据不仅可以解释为技术欠债的指标,而且(意外的惊喜)还可以解释为表明人们不太精通编程/特定技术。“您只是在代码中犯了太多的错误”。

如果存在以这种方式误解数据的风险,则有助于将其他参考数据与WTF不太容易比较的内容进行比较。

  • 假设有两个由相同开发人员维护的相似组件/应用程序,第一个以“废品率”大约50%释放,第二个以80-90的比例释放,这很有力地支持了第二个技术债务。

如果项目中有专门的测试人员,他们也可以为数据的客观评估做出贡献。正如我在另一个答案中提到的那样,

有了测试人员,您就可以找人来备份您对设计问题的理解。当只有开发人员抱怨代码质量时,这通常听起来像是闭门造车的主观WTF
 
但是,当质量检查人员回应这一点时,他说类似component A10个新功能有100个回归错误,而component B每20个新功能中有10个回归错误,沟通突然变成了另一场比赛。


2
我很喜欢这个答案。拥有专门的质量检查部门,回归缺陷与新缺陷的比率非常容易计算,可以肯定地告诉您很多技术债务。
Erik Dietrich '02

4

我认为问题是“偿还”您的技术债务需要花费多少费用-也就是说,要解决该问题需要进行多少工作?好吧,这取决于团队来解决。

在进行冲刺计划时,我要求团队以估算用户故事的复杂性的相同方式来估算修复技术债务项目的复杂性。在那一点上,这是团队与产品所有者之间的谈判游戏,以确定哪些技术债务具有足够的优先级以在当前sprint中完成(取代实际的用户案例)以及可以等待什么。

如果您不做事,我会坚持我的前提-技术债务应以补救费用来衡量。


因此,就故事要点而言,如果代码的受影响区域所代表的技术债务很高,您可以在每个故事中添加几个要点吗?也就是说,如果故事X涉及在代码元素Y中添加代码,这简直太糟糕了,那么由于Y的本质,您会在故事上加上一些要点吗?该点数与执行您提到的估计修复的点数相同或相关?
Erik Dietrich '02

1
@Erik Dietrich-嗯,TD肯定会增加解决方案的复杂性。困难可能是,固定TD零碎可能比批发解决方案更昂贵。因此,如果消除了TD,则可能有3个故事,每个故事的评分为5,但有欠债的则为每个故事8,因此TD总计为9分。整体上确定TD的任务(与故事无关)实际上可能是8。因此,您可以说批发解决方案的成本(8)比零碎(9)小。这将是谈判的一部分
Matthew Flynn'2

那讲得通。而且,当然,我要寻求的是提出一个(有点)客观的案例,例如:“在一年之内,只要我们不断努力,就可以开发X个新功能,而如果我们继续努力,则可以开发X + Y个新功能。还清一些技术债务”。
Erik Dietrich '02

2

有一个相当强大的平台,称为CAST在大型应用中寻找技术债务。我们在一个项目中使用了该项目,该项目对遗留系统进行了重大改进。它不会告诉您编写代码的人的头脑,但是它会检查代码并查找代码和体系结构缺陷,然后根据需要量化为技术债务。但是,查看此内容的真正用途不是$金额,而是代码中已经存在的问题列表。这告诉您您所欠的部分技术债务(因此,我不同意上面提到的一些答案)。有些技术债完全基于设计,而且非常主观-例如色情-当您看到它并知道上下文时就知道了。我会争论这是否真的是“技术性”债务。有一些技术上的债务完全是在实施过程中,我认为这是“


我在Twitter上分享了这个问题,有人回答了有关CAST的问题。在查看他们的网站后,我不清楚该怎么做。是否有免费的赠品或演示版本可以进行试驾?
Erik Dietrich '02

2

这是麻省理工学院之外的一个网络研讨会,描述了有关大型软件系统中技术债务的研究:http : //sdm.mit.edu/news/news_articles/webinar_050613/sturtevant-webinar-technical-debt.html

作者编写了代码来分析项目并提取“架构复杂性”指标。这些指标显示出与缺陷密度,开发人员生产率和开发人员流动密切相关。

网络研讨会中描述的工作建立在哈佛商学院的Alan MacCormack和Carliss Baldwin进行的模块化研究的基础上。我也会看他们的论文。他们的“传播成本”可能就是您想要的。


1

我想说标准代码度量可以用作技术债务的高级相对视图。VS Ultimate包含一个代码分析器,该分析器将基于循环复杂性,耦合,LoC和继承深度为您提供“可维护性索引”。您可以深入研究任何故障点并查看详细信息(直至功能级别)。我只是在项目中运行它,而在数据包(配置和初始化EF)和测试套件中得到的最低分是69。其他都在90以上。还有其他工具可以为您提供更多指标,例如 Bob叔叔的PPP中讨论的指标


因此,假设您的测试套件或数据包中没有某些东西的得分低于90。您是否有一个数字阈值,您会说:“好吧,这还不够好,我们将进行重构”?或者,您是否使用此信息向管理层或某些利益相关者证明有必要进行重构?也就是说,经理/利益相关者是否在乎Microsoft的可维护性指标,或者您是否以其他方式显示该信息?或者,您只是不展示它,而是自己安静地解决此问题?
Erik Dietrich '02

我喜欢这个问题。我的回答将始终是,编写您能做到的最好的代码并不是您要获得许可的事情。我使用Bob叔叔所说的“ boyscout规则”(总是使代码保持比到达时更好的状态),并且我称之为机会重构。这个想法是,当您必须修改现有代码时,请花一些时间a)在单元测试中发现它b)重构它以使其更简洁。迈克尔·费瑟斯(Michael Feathers)有效地使用“遗留代码”,为执行此操作提供了一些指导。
迈克尔·布朗

@ Mike-这将使您在许多开发环境中被解雇,在该环境中,将跟踪和监视对所有代码更改的严格控制。尤其是如果您看似无辜的改进(没有人告诉您进行纠正)最终破坏了曾经起作用的东西。
Dunk 2012年

请注意,我并不是说深入研究并愿意清理代码。我说过要清理您已经在使用的代码。我还使用了高度规范的代码(分配了一个工作项,必须提供所做的更改列表以处理该工作项以供批准,执行批准的更改)。9/10次解释更改请求中的重构将导致批准。
迈克尔·布朗

0

我不会将技术债务视为美元,而您需要一个幻想模型来对其进行量化。我认为这是有利的。如果有人帮您一个忙,而您可能会忘记,请写下来。当您捷径时,将其写下来。这可以帮助您记住,并且更加无能的迫使您承认它。不需要花哨的工具。记事本或Ecxel可以解决问题。


2
从现实政治的角度来看,我认为最愿意为短期结果带来长期不利影响的人们可能也是最不可能记录其决定的人们。因此,我在理论上同意您的想法,但我认为连续的“青睐请求者”最不可能追踪青睐的平衡。
Erik Dietrich'2

@ErikDietrich-我同意。更糟糕的连环犯人甚至都不知道他们正在增加自己的债务。(类似于最严重的信用卡违法者破坏了他们的信用等级。)但是起点是假设量化的愿望,非发行人很难量化。除非它是您的狗,否则您不知道便便在哪里,或者您碰巧踩了它。
MathAttack '02

0

我为一家正在研究此问题的公司工作。以下是我们建议在解决技术债务时应考虑的3个可行指标。有关“如何”和“何时”进行跟踪的更多信息,我们汇总了文章3:了解和处理技术债务的指标

你怎么看?很高兴回答任何问题,很想听听您的反馈意见:)。

防止缺陷和不必要的技术债务的所有权

所有权是工程健康的主要指标。

随着时间的流逝,代码库中收到来自许多人的贡献的部分会积聚残骸,而那些收到来自较少人的贡献的部分则处于更好的状态。在一个紧密协作的团队中维护高标准比较容易,因为他们对代码库的组成部分了如指掌。

这提供了一定的预测能力:随着时间的流逝,代码库中拥有不足的部分可能会积累债务,并且变得越来越难以使用。特别是,很可能无意间承担了债务,这仅仅是信息不完整和对代码质量的所有权过低的副作用。

这在某种程度上类似于公地的悲剧

凝聚力改善架构

内聚性是定义明确的组件的尾随指标。

长期以来,凝聚力及其对应的耦合(coupling)一直被认为是设计软件时要重点关注的重要概念。

当代码的大多数元素都在一起时,它具有很高的凝聚力。高内聚性通常是可取的,因为它与可维护性,可重用性和鲁棒性相关。高内聚力和松散的耦合往往并存。

除了与更可重用和可维护的代码相关联之外,高内聚性还最小化了需要参与修改代码库给定部分的人员数量,从而提高了生产率。

找出问题区域

流失(重复的活动)有助于识别和排名成熟的区域,以便在成长的系统中进行重构。

随着系统的发展,开发人员越来越难以理解其架构。如果开发人员必须修改代码库的许多部分以提供新功能,那么他们将很难避免引入导致错误的副作用,并且他们的生产力会降低,因为他们需要熟悉更多的元素和概念。

这就是为什么争取单一责任来创建更稳定的系统并避免意外后果的原因。尽管某些文件是体系结构中心,并在添加新功能时保持活动状态,但是最好以一种使文件封闭的方式编写代码,并严格检查,测试和质量检查搅动区域。

Churn对这些活动文件进行表面处理,因此您可以决定是否将其分解以减少代码库中更改的表面区域。


-1

如果您通过Bugtracker或某种敏捷软件拥有良好的历史记录,则可以使其保持简单。完成基本任务所花费的时间。此外,该项目在年轻与现在之间的估算的可靠性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.