正确管理技术债务可以决定软件项目的成功和失败。另一方面,忽视或未能识别技术债务可能导致更高的开发成本和更低的商业回报。有这么多的利害关系,理解和处理技术债务应该是软件开发人员和高级决策者的优先事项。
本文是技术债务的初学者指南。我们解释了该术语的含义,它如何影响软件开发项目,以及如何最好地衡量组织中不同类型的技术债务。我们还提供了一系列有效的实践来帮助控制技术债务。
技术债务定义
技术债务(也称为技术债务、代码债务或简称TD)是在软件开发过程中为了获得短期成果而走捷径的结果。开发人员推迟了某些工作以达到可交付成果或截止日期,但“陷入债务”,他们必须通过未来的返工来偿还。
当开发人员依赖易于实施、次优的编码或设计解决方案来加速生产时,通常会出现技术债务。然后,团队必须(在某个时候)返回该产品以添加更多功能或修改代码。以下是公司在质量和速度之间进行权衡的一些常见原因:
- 测试市场契合度的战略决策。
- 时间表或预算限制。
- 糟糕的软件设计选择。
- 编码技能不足。
- 有缺陷的商业决策。
技术债务的功能与任何其他类型的债务一样:您在短期内获得便利,但以后必须支付利息和利息。快速修复和低于标准的解决方案加速了软件开发,但在未来解决这些问题是昂贵的、受限的和耗时的。未解决的技术债务的一些常见症状是:
- 导致性能问题的产品错误。
- 更长的发布周期和上市时间。
- 代码质量问题。
- 降低团队的敏捷性和生产力。
- 负面的用户体验。
- 更高的总拥有成本。
- 可利用的网络安全漏洞。
- 扩展和采用新技术的困难。
敏捷宣言的作者 Ward Cunningham是第一个使用术语技术债务来描述累积技术问题的影响的人。他还使用术语“ cruft ”来描述敏捷团队需要修复或“回馈”以消除技术债务的隐秘代码问题。
技术债务的类型
虽然技术债务总是具有影响力,但不同类型的债务比其他债务风险更大。您产生的债务可能是故意的,也可能是无意的:
- 当公司有意识地延迟解决问题以实现既定目标(例如,向用户发送 MVP 以筹集资金或获得概念验证)时,就会出现故意技术债务(也称为主动债务)。
- 无意的技术债务(也称为被动债务)是偶然或由于粗心造成的,例如选择错误的平台或编码错误。
Martin Fowler 的技术债务象限通过定义两种类型的故意债务和无意债务进一步细分了技术债务的类型:
鲁莽 | 谨慎 | |
---|---|---|
商榷 | 当团队知道缺点但没有立即计划如何或何时解决问题时 | 当开发人员知道他们正在积累兴趣但决定现在发布并稍后修复错误时 |
不经意间 | 当开发人员盲目地实施解决方案而没有意识到他们正在负债时 | 当团队在发布后了解到实施错误时 |
我们还可以根据团队“欠”什么来区分不同类型的技术债务,例如:
- 建筑债务。
- 建立债务。
- 代码债务。
- 缺陷债务。
- 设计债务。
- 文件债务。
- 基础设施债务。
- 处理债务。
- 需求债务。
- 服务债务。
- 测试债务。
技术债务总是不好的吗?
技术债务本质上并不坏。大多数开发团队无法避免偶尔在速度、成本和质量之间进行权衡。只有在以下情况下,技术债务才会成为一个问题:
- 不知道债务。
- 忽略被指控的债务。
就像稳健的金融债务一样,智能技术债务在某些情况下可以带来巨大的好处。战略性债务可以帮助:
- 尽早交付 MVP 解决方案。
- 确认概念验证。
- 确定产品/市场契合度。
- 获得快速反馈。
- 快速满足客户需求。
技术债务对项目的影响取决于团队如何处理他们所欠的。如果公司: 技术债务可能是一种有价值的工具:
- 有意识地决定负债。
- 有资源和知识来偿还债务。
技术债务也是不可避免的。软件开发不断发展的本质意味着每个产品都需要随着时间的推移进行维护和重建。
技术债务示例
以下是故意和意外技术债务的三个真实示例。
示例 1:审慎而深思熟虑的技术债务
- 技术债务:不灵活的框架。
- 欠债原因:管理层设定了一个较短的期限,以快速进入市场并获得“先行者”优势。
- 债务描述:开发人员选择了一个可以快速构建但存在已知灵活性问题的框架。
- 债务回报:将应用程序重构为更灵活的框架。
在此示例中,团队使用具有已知问题的框架来实现早期发布。一旦公司达到目标,开发人员就会回去重构组件并消除代码问题。
示例 2:鲁莽和无意的技术债务
- 技术债务:低质量的代码。
- 欠债原因:缺乏编码经验。
- 债务描述:开发人员的编码技能很差,因此团队在努力满足紧迫的最后期限时编写了低质量的代码。
- 债务回报:清理和重写有问题的代码。
在这种情况下,陷入技术债务不是计划中的决定,而是技能低劣的结果。该团队发布的产品存在错误,这些错误会增加云成本并增加客户流失率。偿还债务的唯一方法是聘请更有经验的开发人员重新编写代码。
示例 3:鲁莽和蓄意的技术债务
- 技术债:错误的网站平台。
- 欠债原因:开发人员更喜欢使用 WordPress。
- 债务描述:开发人员选择在 WordPress 上建立一个高流量的电子商务网站,因为他们更喜欢使用该 CMS。
- 债务回报:将网站迁移到新平台。
在此示例中,团队使用 WordPress构建电子商务网站。CMS 无法处理高流量,导致客户放弃购物车并转向竞争对手。唯一的解决方案是将网站迁移到更合适的平台。
技术债务的原因
技术债务有四种根本原因:
- 业务原因:公司需求有时会阻碍最佳开发实践。更快或更少钱发布产品的压力是技术债务的常见原因。
- 上下文切换:有时,对初始设计有意义的计划会随着时间的推移而失去意义。技术堆栈发生变化,系统变得过时,因此团队经常采取捷径来保持系统运行和(在某种程度上)最新。
- 开发原因:当您在编码过程中引入不足的资源、糟糕的文档和缺乏测试时,就会发生基于开发的原因。
- 基于人的原因:缺乏经验或动力、沟通不畅、团队分散和资源转移是技术债务的常见原因。
以下是一些技术债务原因的真实例子:
- 一个不合理的最后期限,迫使团队快速发布。
- 使用更简单、熟悉的平台,而不是最佳平台。
- 低质量的软件设计决策。
- 项目目标的前期定义不佳。
- 缺乏编码技能。
- 缺乏产品所有权。
- 依靠快速而有风险的创可贴修复,而不是完全重构。
- 测试不足(QA 和 QC)。
- 对软件架构的理解很差。
- 在不参考支持文档的情况下编写代码。
- 紧急的、最后一刻的规格变更。
- 由不同开发人员进行的一系列产品改进。
- 在未来需要合并的多个分支上并行开发。
衡量技术债务
以下是有助于评估组织中技术债务水平的指标:
- 新错误与已关闭错误:如果开发人员在修复错误时创建注释,您可以计算团队消除技术债务的效率。如果新错误的数量超过已关闭的错误,您应该进行一些更改。
- 代码质量:代码质量通过计算圈复杂度、类耦合、代码行数和继承深度来量化代码的整体状态。更高的代码质量分数意味着产品中的技术债务更少。
- 周期时间:该指标衡量第一次提交和部署之间的时间。较短的周期时间表明技术债务较低。
- 代码流失:该指标显示团队在发布后重写或替换一行代码的次数。任何代码区域的长期高流失率表明迭代存在错误或快速修复。
- 代码覆盖率:该指标衡量运行测试套件时执行了多少代码。代码覆盖率通过评估未使用的行数来揭示代码的效率。
- 技术债务比率 (TDR): TDR 有助于计算技术债务的总体未来成本。该指标是修复系统的成本(修复成本)与开发系统的成本(开发成本)的比率。
如何减少技术债务?
没有一种万能的方法来减少技术债务。一些适用于小型初创公司的策略并不总是适用于解决企业级系统问题的 100 多人团队。然而,每家公司都应该采取两个总体方向来控制技术债务:
- 尽量减少新科技债务的产生。
- 尽可能高效、定期地偿还现有债务。
让我们看看您可以使用哪些不同的最佳实践和策略来控制当前的技术债务并限制出现的新错误的数量。
追踪并剔除“垃圾”
跟踪和消除垃圾至关重要,因为技术债务可以在多个开发周期中幸存下来。处理工艺是一个五步过程:
- 技术债务清单:开始并维护公司的技术债务清单。跟踪团队知道代码不干净的所有实例以及需要未来返工的版本。
- 对杂项进行分类:根据技术债务的复杂性、修复成本和潜在影响将技术债务分组为可行的单元。
- 评估债务:注意忽略每个单位的后果。此描述性指标有助于确定任务优先级。
- 使列表易于访问:粗略的列表应该对公司中的所有相关方(利益相关者、营销、销售、SecOps等)都是可见的。
- 尽早并经常删除垃圾:为开发人员安排定期(和频繁)时间来偿还技术债务并保持产品清洁。
这个过程应该是连续的,并且是每个发布周期的一部分。理想情况下,杂乱无章的跟踪和删除应该是您的开发或DevOps 团队的 KPI 之一。
不要雇用低质量的开发人员
即使在积极解决现有错误时,低质量、廉价的开发人员也会产生更多的技术债务。当您考虑交付性能较低的产品所造成的收入损失时,低质量的开发人员花费的成本比您为经验丰富的团队支付的费用要高。
在招聘开发人员时,您应该接受以下两种心态:
- 价值超过价格。
- 质量而不是数量。
较小、较好的团队比较大、技能较低的部门运作得更好。雇佣两名顶级开发人员通常比雇佣十名表现不佳的程序员更好。一旦你有两个可靠的工程师来指示方向并监督发布,你就可以开始引入初级员工进行内部培训。
编写高质量代码
这种做法与上述做法有关;通过衡量以下指标来确保团队编写高质量的代码:
- 代码复杂性(圈和认知)。
- 类耦合。
- 代码行。
- 继承的深度。
- 阿里蒂。
- 可维护性指数。
- Halstead 复杂性度量。
- 是时候写 n 行了。
密切关注这些指标有助于推出低负债软件产品。请记住根据高水平的工作而不是编写代码的数量来奖励员工。还可以考虑创建编码风格指南。通过记录理想的编码实践,团队会发现更容易编写更简洁的语法并花更多时间审查代码。
使用自动化而不是手动测试
手动测试不是控制技术债务的长期选择,这就是为什么您的团队应该转而寻求建立和依赖自动化测试的原因。虽然建立和维护自动化测试需要时间和精力,但缺少手动测试将确保您更准确、更一致地发现问题。
保持透明的更改记录
开发团队应持续记录存储库中的所有更改。如果出现问题,开发人员可以轻松追踪其来源并记录债务。此记录还有助于分布式团队和需要仔细更改的高度复杂的项目(例如迁移到云或对遗留软件进行现代化改造)。
创建技术债务团队
并非每个开发人员或利益相关者都应就技术债务做出决定。决策应该来自了解项目并具有产品权衡经验的合格团队成员。
考虑在您的公司内建立一个专门的团队来制定与技术债务相关的决策。这个团队应该:
- 对您的产品有深入的了解。
- 具有在质量和速度之间进行战略权衡的经验。
- 对团队承担债务的原因保持透明。
- 以非技术性的方式与高层管理人员沟通债务的目的。
- 概述最佳修复方法。
- 创建一个路线图,说明团队将偿还债务的人员、时间和方式。
- 确保开发人员遵守计划并在商定的时间表内解决技术缺陷。
并非每个机会都值得为之举债,因此专门的团队还应评估技术债务墙上的选择权。
留出时间和资源来解决债务问题
优先考虑良好的文档和质量代码至关重要,但您还需要确保您的团队有足够的时间和资源来处理技术债务。调试产品和解决问题既耗费资源又耗费时间,因此如果开发人员面临不断交付新功能的压力,他们将无法解决与债务相关的问题。专家建议,平均 Scrum 团队应该将15% 到 20% 的 sprint 周期用于重构代码和修复与债务相关的错误。
确保定期代码重构
你的团队应该定期进行代码重构,以确保持续偿还技术债务。重构是重组杂乱的代码段以使其更多的过程:
- 可以理解。
- 可维护。
- 可靠的。
重写软件产品中的组件可以消除冗余并提高性能,这两者对于偿还技术债务至关重要。您还应该考虑改进团队的代码审查程序并引入代码检查(自动检查源代码中的程序和样式错误)。
调整贵公司对“完成”的定义
开发一个可重复的公式,指导开发人员如何进行实验或向产品添加新功能。该程序应包括可管理技术债务的标准,因此在软件满足设定要求之前,团队不应将任何产品视为“完成”。
在速度和质量之间取得适当的平衡
只要您的团队明白他们必须“偿还”他们的技术债务,采取战略捷径并偶尔以质量换取速度,就可以为您带来相当大的竞争优势。快速上市和快速概念验证是当今市场的一切,因此明智地使用技术债务并确保团队主动管理平衡以避免未来的障碍。