2019 年提升软件质量的五大方法
封面照片由 Kira auf der Heide 在 Unsplash 上拍摄
2019年初,我管理的开发团队被赋予了一个极其艰巨的目标:实现前所未有的软件质量。鉴于我管理的遗留代码和技术债务数量之巨,我知道我们的工作将异常艰巨。
接下来,我们开始疯狂地寻找各种方法来提高软件质量,并尽一切努力防止错误到达最终用户。
我创建了我的网站Kill All Defects来收集有关软件质量的想法,但即便如此,一些实践和技术仍然值得我与整个社区分享。
因此,我们在这里列出了 .NET 和 TypeScript 开发经理 2019 年最重要的 5 项质量实践(无特定顺序)。
庆祝质量实践
我们常常赞美那些为了赶在关键截止日期前完成任务或修复严重漏洞而夜以继日的英雄事迹。这些事确实值得称赞,也应该受到赞扬,但它们不应该成为被赞扬的重点。
问题在于,我们倾向于赞扬那些破门而入解决问题的消防员,而不是那些默默地做好本职工作、从一开始就防止火灾发生的消防队长。
消防队长获得赞扬的唯一方式是,在事情开始之前明确寻找英雄主义活动来确保质量,因此,作为经理和团队成员,我们需要这样做。
当您看到同事或员工采取积极措施来保证软件质量、及早发现缺陷或从一开始就避免出现各类缺陷时,您需要在私下和公开场合给予果断而正式的表扬。
这应该是一件大事。比按时完成一个关键功能或解决一个紧急问题更重要。
为什么?
正如我们常说质量很重要一样,人们也知道一个组织会奖励什么、谈论什么。正因如此,我们需要确保在偿还技术债务的同时实现卓越的质量,这已经成为我们团队和组织根深蒂固的理念,否则对质量的追求就永远不会真正实现。
代码审查具有巨大的投资回报
2019 年初,我负责审查团队的所有代码。有时除了我之外,还有其他人参与审查,但我会从高层次上仔细检查代码,看看我们做了哪些类型的更改,是否有测试,是否遵循了正确的代码模式,以及每次提交是否都在偿还技术债务。
这还不够。
直到我查看了上半年的汇总数据后,我才开始注意到我们遇到的错误类型和我们所犯的错误在代码审查中的趋势。
而我发现,我在代码审查过程中所做的快速浏览是不够的。
通过将我处理每个合并请求所花的时间增加一倍或三倍,我能够:
- 通过发现更多问题,为我的团队提供更多潜在缺陷防护
- 更全面地了解每个变化
- 发现更多教学时刻来交流最佳实践
在上面列出的这三个好处中,您可能会认为第一个是最重要的,但事实证明,通过关注代码审查,我们获得了最大的好处,因为个人可以借此机会更多地了解软件、一般编程和软件质量。
除此之外,我们还制定了双审阅者政策,即每个合并请求至少应有两位审阅者——最好是一位资深的审阅者,一位初级的审阅者。这有助于其他人从其他人的编程和软件审阅经验中学习更多。
我还制定了一项标准做法,即向大家提问如何确保提交的代码有效且不会引起其他问题。这听起来可能有点傻,但事实证明,工程师们在知道在进入质量保证阶段之前会被问到测试计划时,会更加认真地测试他们的代码,并记录他们在这方面所做的工作(这有助于我认可和奖励他们的努力)。
总的来说,通过在每个冲刺阶段稍微降低我自己的能力,为代码审查腾出更多专门的时间,我们大大提高了团队的整体素质和技能水平。
固定测试非常有价值
2018 年我读过的最好的书是Michael C Feathers 的《有效处理遗留代码》。然而,直到 2019 年我才完全实践了其中的一些做法。
具体来说,Michael 讨论了“固定测试”的概念——即旨在固定当前应用程序行为的测试。无论测试结果正确与否,如果任何未来的变更导致系统行为发生变化,则固定测试应该失败。
这些对于基于计算或转换的算法以及诸如减速器之类的东西最有效,我使用了很多这样的算法。
我最早的固定测试是手动测试,通过检查属性与预期结果来比较对象,但这些测试非常繁琐。
然后我遇到了Jest。Jest是一个 JavaScript 单元测试框架,它的功能包括快照测试。快照测试将对象序列化为 JSON,并将该 JSON 与测试首次运行时存储的原始对象状态的 JSON 快照进行比较。
这实际上允许您在一个ShouldMatchSnapshot
断言中编写一个固定测试,这既非常强大,也很容易被滥用。并非每个测试都应该是固定测试——大多数都不应该,但您需要一些广泛的测试来提供安全网,同时进行更具体的行为测试。
有关 JavaScript 或 .NET 中基于快照的测试的更多信息,请参阅我关于该主题的文章。
然而,关于这些测试需要强调的关键一点是,如果没有固定测试的广泛覆盖,我就没有勇气像今年这样偿还技术债务,或者以同样的勇气偿还。
用科学方法偿还技术债务
从2019年8月底到年底,我写了大约80篇文章。但如果我只能分享一个库的话,那就是“科学家”系列库。
科学家允许您将某事物的旧实现与同一事物的新实现进行比较,并比较两种算法的结果和性能。
您可能想知道这与我在上一节中提到的快照测试有何不同。
这里的主要区别在于,Scientist 旨在根据来自实际最终用户的数据在生产中运行,而不是根据您在开发和测试期间向其抛出的各种测试数据运行。
这就是 Scientist 的核心优势所在:如果我编写了一个新版本,速度更快、效率更高、更易于维护,但 5% 的用户会遇到错误,我可能直到代码投入生产时才会发现这些问题。而使用 Scientist,新程序中的错误仍然存在,但用户将获得旧版本算法的结果。
这意味着我们可以在生产环境中有效地对新代码进行金丝雀测试,而不会给任何最终用户带来任何缺陷或不良行为。如果发生错误,我们可以将其记录到某种形式的异常监控服务、日志文件或数据库中。然后,我们可以随时发布基于该修复实现的新版本,并确认不会再发生其他错误。
只有当我们对新代码的质量完全满意时,我们才会将 Scientist 从组合中删除,并让新版本的代码接管。
要详细了解这一点,请查看我关于 Scientist .NET 的文章。
代码质量需要能够沟通
我们每个人都或多或少地处理技术债务。
技术债务是优先级变化、范围变化、技术创新以及我们随着时间的推移技能和才能增长的自然副产品。
但技术债务只对开发人员重要,除非你能以产品管理和业务管理能够理解的方式传达它。
这样想想:如果我来找你并询问你的技术债务,你会告诉我什么?
如果我问你情况是变好了还是变坏了,你会怎么说?你能证明吗?
如果我问技术债务在生产力损失和错误出现方面造成最多问题的地方在哪里,您能准确回答吗?
如果我给你一天时间来解决技术债务,你会把它花在哪些方面?一周呢?你为什么要把它花在那些方面?你准备好不做任何规划就直接开始了吗?
这些问题都非常合理。实际上,这些都是比较简单的问题,我并没有明确地想挑战你,说你的技术债务不重要。
所以我的观点是:除非你能向他们解释清楚,否则技术债务对企业来说就像一个模糊的幽灵。
这是一个复杂而微妙的话题,我已经写了很多相关内容。
一个好的起点可能是我关于沟通技术债务的文章。
如果您与不太了解技术债务的人一起工作,您可能会喜欢《定义技术债务》。
如果您的组织认为技术债务并不是真正影响业务的因素,您可能需要阅读《技术债务的真正成本》。
如果其他人意识到技术债务,但犹豫是否优先偿还,我建议与他们合作,将技术债务视为风险。
最后,如果您希望始终掌握有关代码异味趋势的经验数据,您可以查看自动代码分析工具,例如NDepend for .NET。
是的,我知道有很多链接,但技术债务是一个非常微妙的话题,很难将许多广泛的文章浓缩为年度回顾文章的单个部分。
结束语
我给你介绍了很多东西。我经常这样做。我喜欢向别人介绍一些他们可能没有考虑过的工具和实践,这样当他们觉得这些工具和实践有意义时,就可以进一步研究。
如果您希望我深入探讨这一系列主题中的任何内容,我很乐意在 2020 年大步前进的同时为您提供帮助。
至于我的团队:虽然我们仍然允许少数错误存在,但这些错误通常都很轻微,并且很快就得到了修复。我在这里概述的这些技巧和技术,对我们的软件开发方式以及培养真正注重软件质量的团队文化产生了显著的影响。
祝您未来一切顺利,并希望 2020 年是一个缺陷少而又少的一年。
2019 年提高软件质量的 5 大方法一文首先出现在Kill All Defects上。
鏂囩珷鏉ユ簮锛�https://dev.to/integerman/my-top-5-ways-to-improve-software-quality-from-2019-3fnj