并非所有技术债务都应得到平等对待

发布于:2021-02-18 00:00:05

0

95

0

技术债务 发行软件 测试 代码

发行软件就像抵押。您要保持不变的债务,必须在测试,维护和代码行中偿还债务。如果您无法继续支付,您可能会失去全部。

技术债务的隐喻越来越受到关注。最初,沃德·坎宁安(Ward Cunningham)在1992年首次使用该词,其描述如下:“首次交付代码就像负债累累。只要通过重写及时偿还债务,债务就可以加快发展速度。如果不偿还债务,就会发生危险。花在不完全正确的代码上的每一分钟都算作该债务的利息。整个工程组织可能会因为未合并的实施,面向对象或其他原因的债务负担而停滞不前。”

有趣的是,许多敏捷开发方法的发起者现在都认为对技术债务的持续管理对于开发高质量和可维护的软件至关重要。

这挑战了开发决策几乎应完全由业务价值驱动的想法,因为很难评估偿还技术债务或将时间投入到可靠的软件体系结构中的价值。在我看来,管理技术债务和扎实的架构基础的价值与项目规模的线性增长相比,增长的幅度更大。

如果您的项目只有几千行代码,而团队只有2到3个人,则通过连续重构按需添加体系结构相对容易。但是,一旦我们拥有成千上万的代码行,不断开发新功能以及扩大团队规模,事情就会变得复杂得多。在这种情况下,如本研究报告中所述,技术债务的管理和对坚实的建筑基础的投资将带来巨大的收益。

问题是如何衡量技术债务并关注正确类型的技术债务。我将首先讨论技术债务的衡量,然后深入探讨技术债务的不同类别及其对项目成果的影响。

衡量技术债务

要衡量技术债务,我们需要一个更精确的定义。您如何用更多技术术语来定义“不太正确”?好吧,您可以根据编程规则,体系结构规则和其他规则定义“正确”。然后,您可以计算违反规则的次数,以估算出软件系统中技术债务的金额。该技术债券插件的 SonarQube使用的正是这种做法拿出的金额为系统中的技术债务。

不幸的是,细节在于魔鬼。您如何权衡各种违规行为?您的费用依据是什么?首先检查哪些规则?这些规则真的相关吗?如果使用默认配置,则会发现许多内置规则并不完全相关,因为它们对软件质量或可维护性缺乏可测量的影响。

另一方面,通常根本不考虑重要因素,例如系统与体系结构蓝图的一致性,耦合度量和结构健全性。这意味着您可能正在寻找误导性的数字,并花费大量精力解决不相关的问题。

因此,重要的是要拿出自己的规则集并相应地配置测量平台。经验法则是少即是多。从一些有意义的规则开始,然后如果发现规则没有检测到重要的缺陷,则随着时间的推移扩展您的规则集。要确定某个规则是否将其纳入您的规则集中,请始终问自己,违反此特定规则将对系统的质量和可维护性产生多大影响,以及在以后解决违反问题的难度如何。

显然,我们应该关注具有相对较高影响力和/或较高维修成本的规则。在本文的结尾,我们将介绍一个示例规则集,该规则集在我自己的公司和许多客户中都非常有效。

技术债务类别

对规则进行分类很有意义,这样可以更轻松地查看全局,而不会迷失在非常具体的技术规则的细节中。以下是一些明显的规则类别:

  • 本地编程规则,例如“无空catch语句”等

  • 基于自动测试和测试范围的规则

  • 基于软件指标(即指标阈值)的规则

  • 基于架构和依赖结构的规则

现在让我们考虑这些类别对维修成本的总体影响以及对可见质量和代码可维护性的影响。术语“可见(质量)影响”用于描述软件系统用户可直接检测到的事物,即错误和不良程序行为。术语“可维护性”用于涵盖代码可理解性和代码可更改性等方面,即对更改成本的影响。

{xunruicms_img_title}

在测试和测试范围方面,如果必须在开发后创建测试,则维修成本可能会很高。理想情况下,将创建自动测试以及应该测试的代码。对可见质量的影响也很大,因为缺少测试会增加可见错误的可能性。另一方面,缺少测试对可维护性没有很大的影响–除了良好的测试覆盖范围使全局重构变得更加容易之外。违反编程规则的问题很容易修复,因为修复程序通常只需要更改单个文件即可。有时违反编程规则也会导致可见错误,因此我将对可见质量的影响分类为中等。可以忽略可维护性影响,因为违反本地编程规则不会影响整体代码可维护性。

基于度量的规则通常具有较低的修复成本,但涵盖全局方面的度量(例如系统内的整体耦合)除外。流氓指标值也很少会产生可见的问题,但是对可维护性肯定会有很大影响。

我们的最后一类涉及架构和依赖项结构。对于度量标准,很容易看出,不良或丢失的体系结构不一定会造成明显的问题,因此对可见质量的影响非常低。但是事后修复损坏的架构或添加架构非常困难且昂贵。更改没有清晰体系结构的系统也非常困难。此类别下的所有技术债务也称为建筑债务。

毫不奇怪,大多数尝试跟踪其技术债务的人都将注意力集中在具有明显可见影响的规则类别上。但是,当直接问到这四个类别中的哪一个对项目的生命周期成本影响最大时,大多数人凭直觉就同意这将是“架构和依赖关系结构”。弥合这种明显的差距将提供非常好的投资回报。

结论是,这可能不是以相同方式处理所有技术债务的最佳方法。根据您的战略目标确定规则的优先级很重要。对于较小的项目,仅关注影响可见质量的事物才有意义。您的项目规模越大,寿命就越长,建筑债务的毒性就越大。因此,大型项目应重点关注控制建筑债务。

管理技术债务

既然您实际上可以量化技术债务,则可以就何时累积债务以及何时还清债务做出明智的决定。积累技术债务以应付由重要业务限制所定义的关键期限是完全合理的。只需确保您确实制定了一项计划,可以进一步偿还债务。

跟踪技术债务的另一个好处是,您可以与利益相关者进行更有意义的讨论。如果他们知道过分地要求截止日期会自动导致更多债务的积累,那么就容易达成一致的平衡方法,该方法总是为代码卫生和体系结构分配时间。

随着时间的推移,我了解到,平均而言,您应该在此领域中花费大约20%的总开发工作量,在项目的早期阶段可能会花费更多,而在后期阶段则可能会花费更少。从项目一开始就这样做,将在项目的整个生命周期内节省大量成本。

规则集示例

设计规则集时,您首先要确保可以自动检查所有规则,理想情况下是在连续集成版本中进行检查,或者每天晚上至少进行一次检查。需要人工干预进行检查的规则不应用于技术债务评估。因此,您将需要投资于工具和相关的基础架构。由于某些必需的工具是免费的,并且大多数敏捷团队都已经拥有构建服务器,因此这并不是一个大障碍,尤其是在考虑到潜在节省成本的情况下。

您的规则集还应根据项目的规模反映出您的战略重点。如上所述,较小的项目与较大的项目需要不同的优先级。

此示例规则集适用于较大的Java项目,但可以轻松适用于其他语言。我们假设将SonarQube用作综合性工具,以合并用于衡量技术债务的各种工具的结果。在每条规则的后面,我们列出了实现该特定规则的潜在工具:

  1. 定义一个架构蓝图,并确保代码能够反映该蓝图(Sonargraph,Structure101)

  2. 避免包之间的循环依赖关系(Sonargraph,Structure101,SonarQube)

  3. 测试覆盖率应高于50%(SonarQube与Cobertura或Emma)

  4. 保持较低的整体耦合(示例度量:平均组件相关性低于70)(声纳图)

  5. SonarQube中没有严重或阻止违反的行为(带有FindBugs,CheckStyle和PMD的SonarQube)

  6. 重复的代码行不应超过代码行的10%(SonarQube,Sonargraph)

  7. 源文件的代码行数不得超过700行(声纳图)

  8. 改良的McCabe环复杂度方法不应高于15(声纳图)

  9. 包中最多不能包含50种类型(声纳图)

规则1和2专注于体系结构和依赖关系结构。7、8和9中的度量标准阈值是软阈值,即,如果有记录的原因,可能会违反该阈值。对于规则5,花一些初始时间来配置CheckStyle,PMD和Cobertura的活动规则非常重要,这样可以避免检查规则而没有太多实际意义。规则5可以视为元规则,因为它总结了类别1的所有小规则。根据您的配置,规则可能是几十个,甚至数百个。

规则集在上述不同规则类别之间具有良好的平衡。在我的公司中,违反规则1和2将破坏构建,而其他违反将创建警告。