技术债正在悄悄拖垮你的团队!

2024-11-23  本文已影响0人  JavaEdge

0 前言

软件开发的核心在于应对变化。在软件的生命周期中,目标是能够在合理的时间内实施必要的更改。不管这些更改是技术性的,比如紧急安全升级,还是业务需求所驱动的,比如开发新功能以在目标市场中更具竞争力——能否快速应对变化是成败的关键。

是什么让我们慢下来?通常,这是因为让某个功能能够运行并不等于让它在长期内具备良好的可维护性(参考 Google 软件工程实践)。第一个可运行版本通常是快速而粗糙的,而让其具备可修改性则需要额外的努力。这引出了“技术债务”的隐喻(参考 Ward 的解释)。开发人员选择暂时不投资于代码的可变更性,而是承受技术债务,以便更快完成任务。之后,每次修改代码都需要支付额外的“利息”,直到技术债务彻底清偿。

1 啥是技术债?

技术债务是指当前软件状态与最适合于轻松实现更改的目标状态之间的差距。在某些情况下,积累技术债务可能是值得的——例如,为了满足一个硬性截止日期,否则整个项目可能停滞不前。但从长远来看,采取措施来控制和减少技术债务无疑是明智的(参考 Fowler 的文章)。

对于寿命预计以年为单位的软件来说,是否偿还技术债务并不是问题。问题在于如何识别、衡量和管理它。

技术债务可能有不同的来源。例如,团队可能对技术债务引发的问题缺乏认识;或者,尽管意识到问题存在,但误以为永远没有时间解决。这与工程文化密切相关。随着时间推移,问题只会越来越严重(参考 破窗理论)。另一种情况是,团队在权衡利弊后,有意积累技术债务。第三种情况则是因为我们无法事先掌握所有信息,需求可能变化,而开发过程中会逐步学习。这种债务即使对于最优秀的团队来说也不可避免(参考 Fowler 的技术债务象限)。

技术债务的棘手之处在于,它通过不断做出小的妥协而逐渐积累。为了短期的便利和简单而牺牲长期的结果,被称为“温水煮青蛙隐喻”。换句话说,问题会逐渐积累,直到灾难发生为止。我们如何防止这种情况的发生?

应对技术债务的最佳防御措施是从一开始就使其可见。然后,我们可以通过设立适当的健康指标,并尽早采取纠正措施来主动管理它。

另一方面,如果我们的系统已经因为技术债务濒临崩溃,那就需要采取更激进的“清理”措施——在为时已晚之前。在这种情况下,建议建立多个改进指标,并使用它们来跟踪这些措施的进展。

2 WTFs 每分钟

一个广泛认可的观点是,代码质量的唯一有效衡量指标是每分钟 WTF 次数(参考 Martin 的《代码整洁之道》)。或许可以开发一款设备,专门用来统计 WTF 次数,这或许会成为一个不错的创业点子?

当然,这个指标既主观又依赖于开发者的技术水平及团队的工程文化。根据破窗理论,糟糕的代码越多,就越会鼓励开发人员继续制造技术债务。

3 代码异味的数量

Martin Fowler 和 Kent Beck 引入了“代码异味”这一概念,帮助开发者识别代码中可能存在问题的地方。Fowler 的《重构》一书列举了 24 个代码异味示例。Uncle Bob 的《代码整洁之道》中也包含了许多代码异味和启发式规则(参考《[代码整洁之道》第17章](https://learning.oreilly.com/library/view/clean-code-a/9780136083238/chapter17.xhtml#:-:text=Smells and Heuristics))。一些代码异味,如重复代码和过长函数,可以通过静态分析工具(如 [SonarQube](https://docs.sonarqube.org/9.6/user-guide/concepts/#:~:text=Code smell,errors as they make changes.))轻松检测。然而,许多代码异味无法通过静态工具轻松发现。这也是为什么需要像“每分钟 WTF 次数”这样的另一个指标。

4 自动化测试覆盖率

尽管早在[《Google 软件工程实践》](https://abseil.io/resources/swe-book/html/ch11.html#:~:text=We have a name for,changes across the entire codebase.)、《代码整洁之道》](https://learning.oreilly.com/library/view/clean-coder-the/9780132542913/ch01.xhtml#:-:text=Am I suggesting,be tested. Period.) 等书中提到过自动化测试的重要性,最近的研究(例如《Accelerate》和 DORA 研究)表明,测试自动化与软件生产力之间存在统计上的正相关。这表明,提高自动化测试覆盖率通常可以显著提升团队的生产力。

可以通过许多工具(例如 [JaCoCo](https://www.eclemma.org/jacoco/#:~:text=JaCoCo is a free code,existing libraries for many years.))来追踪这个指标。但如同许多其他指标一样,它也容易被“造假”,比如编写大量实际上并未测试任何内容的测试。因此,结合其他努力来提升团队技能,并阐明编写自测试代码的好处是非常重要的——比如 Google 推行的厕所上的测试

当测试自动化覆盖率较低成为限制团队进步的因素时,这一指标尤为有效。例如,我的团队曾发现某个遗留组件的测试自动化覆盖率非常低(仅约50%)。因此,我们将提高该覆盖率作为优先事项。通过持续监控指标、在团队回顾会议上讨论进展,我们在一年内将单元测试覆盖率提升至80%,并且不再视其为限制因素。现在,我们将其作为代码库健康的一个重要指标。

5 文档覆盖率

文档不足可能对团队效率产生负面影响。因此,我们可以采用一个与文档覆盖率相关的指标:

文档覆盖率:系统中文档覆盖部分占总系统的百分比。

如何使用这个指标?在文档不足被视为制约因素的团队中,可以优先改善这一问题。我们列出所有组件,并评估每个组件当前的文档覆盖情况。每周更新指标,并监控改进进展。

6 用在弃用组件上的精力

在一些情况下,为了支持新的组件,我们需要弃用旧组件,但在一段时间内仍然不得不保留这些组件。例如,有些客户端需要时间完成迁移。在此期间,我们仍可能需要对这些弃用组件进行工作,比如修复漏洞。由于这些弃用组件最终会被移除,这种工作实际上是一种浪费。问题是,团队往往会“忘记”这些弃用组件,继续对它们提供支持。随着时间推移,这些工作会不断积累,甚至可能成为团队的主要限制因素之一。因此,跟踪弃用组件并尽早废止它们是非常重要的。

可以采用以下指标:

如何使用这些指标?例如,我的团队负责一个覆盖 200 多个国家的住宿合作伙伴门户中与发票相关的财务内容。去年,我们开发了一个新的发票展示页面,并在几乎所有国家推出。然而,由于一些国家有特定逻辑,我们决定暂时保留旧页面以便后续迁移。这一决定让我们可以更快地获得新页面的反馈。然而,这也导致我们在几个月内需要支持多个版本的页面。尽管旧页面的支持工作量不大,但累积效应可能会显著增加负担。在这种情况下,我们将这一指标作为改进和健康监控的重要工具。

7 用于修复用户发现缺陷的工作量

软件中的缺陷显然会减缓功能开发的进度。因此,这些缺陷可以被视为技术债务的一部分。

我们可以使用以下指标来量化相关工作量:

8 漏洞的数量

OWASP Top Ten 网络应用安全风险列表中,“漏洞和过时组件”被列为其中之一。这些问题可能导致紧急计划外工作,来修复漏洞和应对后果。因此,漏洞可以被视为技术债务的一部分。

我们可以使用工具 Dependency-Check 来检查项目中的依赖项。将该工具集成到 CI/CD 流水线中是广泛认可的最佳实践。这种方法可以帮助我们尽早发现并修复漏洞或过时组件,从而减少技术债务带来的潜在影响。

9 清偿技术债务所需的估计工作量

有些导致团队效率降低的问题无法通过静态分析工具轻松追踪。例如,共享数据库架构或其他复杂的架构问题,通常难以用工具直接衡量。每个团队都会面临其独特的技术债务挑战,因此解决方法也会有所不同。

最简单的衡量方式可能是估算清偿技术债务所需的工作量。然而,这种估算需要团队具备足够的技能和经验,例如掌握设计模式、重构技巧、自测试代码的编写,甚至是架构最佳实践(如松耦合架构)等。通过结合这些能力,我们可以更准确地评估并应对技术债务。

10 关键总结

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化
  • 活动&券等营销中台建设
  • 交易平台及数据中台等架构和开发设计
  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
  • LLM Agent应用开发
  • 区块链应用开发
  • 大数据开发挖掘经验
  • 推荐系统项目

目前主攻市级软件项目设计、构建服务全社会的应用系统。

参考:

本文由博客一文多发平台 OpenWrite 发布!

上一篇 下一篇

猜你喜欢

热点阅读