一个童话故事
很久以前,有个软件开发团队找到他们的经理。“我们的项目有相当多的技术债务(Technical Debt),我们应该做点什么。”这个团队说。他们展示了一张图(图1)来说明项目的技术债务。“技术债务关系到项目质量。”他们说。并展示了技术债务各部分的分解,通过静态代码分析,能发现过于复杂的代码、重复的代码和冲突。“我们需要去除技术债务”他们告诉经理。
图1:SonarQube技术债务插件的结果报告
但经理困惑了:什么是技术债务?他该额外再增加$500.000的预算?为了什么?这关系到质量,但他不知道现在有什么缺陷。客户一直很满意,这些开发人员在说什么?因此经理和团队进行了长时间的讨论。
事实上,技术债务就是在这类讨论中引入的一个比喻。意思是低质量的代码就像是财务负担。债务的总额就是从代码库中把它们清除出去所需要付出的努力。利率是由于低质量代码造成的生产率下降。管理人员通常熟悉财务领域的术语,所以在谈论软件质量时使用这个比喻会更加容易沟通。
这个故事说明,技术债务这个比喻失败了。本以为在和经理沟通技术质量时,它能起到帮助作用,并最终产生回报。然而,现实并不那么容易。这是因为有技术债务并不意味着它必须要偿还。技术债务甚至不一定是件坏事,有时它只是为了按时上市或者达成项目其它目标而妥协的结果。甚至有时候这种情况无法避免,例如类库采用新技术或者进行了升级,导致原来没问题的代码现在产生了技术债务。关于技术债务该如何偿还,并没有简单的定律。事实上,偿还技术债务有多种方式,或者有时候你甚至可以将它作为你的优势。
技术债务的问题
技术债务的主要问题是它只代表了系统的内部质量。而质量有哪些影响并不明确。特别是,技术债务的经济影响无法简单地用这个比喻来表示。技术债务还很奇怪。如果这些代码不需要修改,那技术债务就完全没关系。但是,一旦要修改这些代码,技术债务就成为代码的所有重要属性。所以,技术债务很可能对项目的成功、外部可见的质量完全没有影响。
但是如果你忽视项目的技术债务,很可能它就在某个地方等着你:如果你需要修改有大量技术债务的代码,成本可能非常高,最终无法执行。开发人员通常知道和害怕这类情形,维护有大量技术债务的代码不仅仅是少了乐趣,而是风险太高,因为bug很可能潜入,而评估很容易就被证明是错的。
因此,软件质量可能对软件项目的成功非常重要,而技术债务的比喻是不够的。它能用来表示软件质量,让人们了解软件质量怎么样,但如何处理软件质量才是真正重要的。
质量投资:修复代码的新比喻
也许换一个比喻更能说明对于软件系统的质量,我们该做什么。技术债务只反映修复质量问题所需支付的成本,上述例子中是$500.000。这个数字本身没有什么用处,它无法说明我们该如何处理这个问题,或者它们如何影响了系统的开发。也许我们该偿还技术债务,也许它完全没有影响。
所以一个更好的比喻也许是质量投资(Quality Investment)。使用质量投资,处理技术债务就有可能获得利润。这样就可以使用财务术语来积极地管理代码质量,可以很容易决定哪些质量问题应该解决,哪些可以暂时接受。
质量投资的想法来源于SQALE。SQALE方法[2][3]是一种质量模型,它定义了两种类型的成本:修复成本(remediation costs,RC)和非修复成本(non-remediation costs,NRC)。修复成本是指在你的代码库中清除某个质量问题的付出。事实上,修复成本可看作是技术债务。第二类成本更有趣。当这个质量问题未解决时,就会产生非修复成本。例如,开发某个新功能可能需要更长时间。这个额外的付出就是非修复成本。在这个上下文中,非修复成本看起来像是技术债务的利润。但事实上,这些成本应该给予更多考虑,例如不清理低质量代码的额外风险因素。利用SQALE,你可以选择维持当前的低质量状态,支付非修复成本,或者去提高质量,支付修复成本。
该质量模型的前期实现,例如SonarQube的SQALE插件,只支持修复成本。然而,这两种成本类型是经济合理地处理质量的关键,也是这个质量模型的创新性所在。
如果你正在提高质量,解决质量问题,那么支付的是修复成本。当问题清除后,团队避免了相应的非修复成本。因此,只有当非修复成本大于修复成本时,才值得去提高质量。因为只有这样,质量投资才能产生利润。这可以简单地用下面的利润公式来描述:
利润 =非修复成本 – 修复成本
这个公式给出了一个合理的、符合经济原则的指导方针,用于判断质量问题是否需要修复,以及何时修复。
正如之前提到的,代码的质量只有当它将来需要修改时,才会变得重要,因为只有这时候团队才会因为低质量代码而慢下来。所以,正确的投资分析必须评估代码将来修改的可能性,以及这两种类型的成本。因此,质量投资的比喻可以通过三个评估来实现。让我们看一个例子以便更深入地了解这一点。
假设我们有一个系统,它包括三个模块:客户、订单和发票。客户管理是个非常老的模块,已经不再开发了。因此,这个模块不适于质量投资:仅当代码被修改时才会产生修复成本,在这个例子中,修改的可能性为0%。因此支付任何修复成本都将导致损失。
然而,我们知道在接下来的迭代中,对订单流程进行了大量修改。根据经验,发票管理也必须进行一些修改。像这样的粗略估计通常是足够的,而且也很容易达成一致。经验告诉我们,详细的评估绝大多数都是假装精确。
接下来的步骤是要评估订单模块和发票模块的质量问题。订单管理的测试覆盖率非常低,客户管理的代码非常复杂,也就是说方法和类有大量的代码,并且有很多复杂的循环。面对众多选择,我们评估了修复成本和非修复成本。非修复成本的评估也应考虑模块修改的可能性。在下一个迭代中,如果代码质量相同,订单管理估计要投入20天。而如果测试覆盖率能提高,那么估计只需投入13天。因此,非修复成本是7天。这非常高,因为质量确实太差了,同时也因为有大量代码要修改。
- 订单管理:很低的测试覆盖率,修复成本:5天,非修复成本:7天
- 发票模块:很高的复杂度,修复成本:5天,非修复成本:4天
这些评估表明订单模块的质量投资产生了2天(=7天-5天)的利润。相反,发票模块的质量投资没有利润,甚至亏损。由此可见,投资于当前的订单系统是有价值的,因为根据团队的评估,提高测试覆盖率就有利润。对于发票模块,情况并不明确。就现在来说,其质量投资没有利润。然而,发票模块很可能在未来的几个迭代中也需要修改。这样你就能从发票模块的质量投资中得到利润。
根据给出的评估和计算出的利润,也可以为每个质量投资推算出投资回报(RoI)。投资回报表示相应的成本产生了多少利润。因此,投资回报率等于利润除以修复成本。订单模块质量投资的投资回报率大约是40%(=2天/5天)。经理们通常会寻找机会去获取比较高的投资回报率。使用这些财务术语,你能与他们沟通代码质量提高后的收益。当然,就像软件开发的几乎所有其它事情一样,这些数字都是估计值。然而,这显示了团队不只是基于自己的原因寻求提高质量,更重要的是由于经济原因。
质量投资这个比喻,让你能与管理者进行各种类型的讨论。除了技术债务的成本,你还可以与经理讨论节省时间和投入。对于经理来说,这意味着双赢局面:节省了预算,开发人员也很高兴,因为他们可以提高代码质量。同样,管理者可以考虑投资是否合适,或者一个快速但质量较低的解决方案也是足够的,甚至是必要的,因为要按时上市。
最后,质量投资是比较了众多评估的结果:什么是最经济的决定?但是,它回避了一个问题,为什么在软件开发中,很少使用投资这种想法。
另一个童话
现在,让我们再重头开始讲这个童话故事,这次采用质量投资的方式。
很久以前,有个软件开发团队找到他们的经理。“我们相信,已经找到一种方法来提升我们的开发。”他们说,“我们进行了一些评估,刚开始时,下一个迭代中订单处理要做的修改非常多。然后,如果我们投资5天用于提高订单管理的测试覆盖率,我们估计下一个迭代能节省7天,所以我们可以少投入2天。”“太棒了!”经理说,“就这样做!这是有价值的投入。”所以这个团队最终提高了大家都关心的模块质量。“另外还有一个,”这个团队说,“如果我们另外再投资5天用来提高发票系统的质量,我们觉得我们将能节省4天。虽然这有点损失,但我们相信在下一个迭代中我们就能赚回来。”经理回答:“好的,但是,在这个迭代中,我们真的要推出尽可能多的功能,这额外的两天非常有用。客户现在不是很高兴,我要让他们看到印象深刻的东西。否则可能就没有下次迭代了……”所以他们得以继续提高订单管理的代码质量,并开心地过着日子。
这说明了质量投资作为一个比喻为什么这么有效:可以用它来评估涉及质量的每个决定的利润。也很容易判断出某些质量投资可能比其它方面的关注,例如实现新功能,具有更高的优先级。如果没有这个比喻,所有这些都是不可能的。当然,只有当团队有质量很高的评估历史数据时这些才有可能。但即使没有,使用这些术语去思考也有利于得出更经济的决定。
CodeQ Invest
CodeQ Invest[4]是一款支持质量投资的工具。它是一个Web应用,能够自动计算包括单个类到根包在内的各级别的代码修改概率。源代码控制系统用于计算合适的数字。它基于这样一种思想,过去经常修改的代码,将来它们修改的可能性要比那些过去没修改过的代码更大。你可以定义这个计算要涵盖的天数。这些天内的每次提交都将用于计算,计算每个修改的文件,代码修改的比例。此外,你能选择不同的方法来计算过去代码发生的变化:
过去n天内,所有提交的权重相同
过去n天内,所有提交的权重逐渐增加(越新的修改,权重越高)
过去n次提交的权重相同
除了自动计算修改概率,你也可以人工评估某些代码的修改可能性。对于进入维护阶段的系统,也就是说不会增加新功能的系统,概率计算是非常有用的。它同时也给出了代码库中的有趣视角和代码中可能的热点。人工评估非常适合于开发新功能时,特别是一些过去未触及的代码必须要修改的时候。
CodeQ Invest还有很多其它功能。它计算你代码库中的最佳投资。你提供预算,也就是投资系统质量的小时数,CodeQ Invest将建议哪些地方的代码应该提升。团队应该为它进行质量配置。该配置从该团队的视角来定义代码质量。不同的团队可能会给出不同的配置。配置包括许多质量需求。每个需求描述代码质量的一个度量角度。CodeQ Invest当前允许你对不同的指标设置阀值。可以使用SonarQube(前身是Sonar)[5]对它们进行度量。SonarQube是非常流行的代码质量管理工具,用于分析代码得到指标值。此外,对每一个质量需求,团队必须评估修复成本和非修复成本。团队只在低层级评估成本,例如,将100行代码的测试覆盖率提高10%需要花费多长时间?基于该测试覆盖率的代码,实现功能有什么影响?该工具为你提供更高层次的抽象与合计。示例如图2。
CodeQ Invest只是一个工具,用于进一步帮助你使用新比喻和新方法来处理代码质量。基础部分是各种评估,它可以以传统的方式完成,即评估故事、质量提升以及在特定故事上进行质量投资的影响。或者你可以使用CodeQ Invest并进行设置,正如你所看到的,设置某些质量特性影响的数量。CodeQ Invest将使用这些基本数据,得到投资计划的相关建议。
图2:CodeQ Invest的项目视图。显示了一个可缩放的树对应你代码库中的投资机会。在右侧你能看到几种预算的投资回报分布(例如16或者32小时)和一个基于给定投资生成的质量投资计划。
总结
尽管技术债务能够帮助沟通软件系统的质量,但对于如何处理这个质量,它并没有太大帮助。这将导致很多问题,例如低质量的代码得不到维护。到最后,主要的关注点是应该提升系统哪一部分的质量,哪些地方是没问题的,不需要修改。而这就是质量投资能够帮助的:每一项提升都根据经济产出来判断,也就是说它是否比保持代码不变更便宜,还是应该投资于质量?这给了一个很好的指导方针,哪些代码的质量应该提升,什么情况下代码质量应优先于实现新功能。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
相关推荐
-
关于何时偿还技术债务的建议
Spotify的敏捷教练Henrik Knibert最近写了一篇文章,论述了为什么有一些技术债务可以成为一件好事以及可以将其作为判断系统质量的依据。
-
多任务只会耽误项目进程?
我打赌你一定上百万次听过这句话:如果你有很多做不完的工作,那么就进行多重任务。但这恰好是非常糟糕的建议。
-
定制化项目管理框架:敏捷/Scrum/Kanban
Scrum、Kanban、精益开发、Lean Startup、DSDM、FDD—这就是字母汤。这些在项目管理中又是如何建设的呢?这其中有没有贵公司拿来就可用的?
-
如何处理敏捷开发中的迭代问题(上)
敏捷迭代几乎总是围绕着将在短时间内建立一组特性来定义。以各种各样的方式描述这些特性——我最喜欢的是用户故事——但它们几乎总是以应用……