一、定义
技术负债(英语:Technical debt),又译技术债,也称为设计负债(design debt)、代码负债(code debt),是编程及软件工程中的借鉴了财务债务的系统隐喻。指开发人员为了加速软件开发,在应该采用最佳方案时进行了妥协,改用了短期内能加速软件开发的方案,从而在未来给自己带来的额外开发负担。这种技术上的选择,就像一笔债务一样,虽然眼前看起来可以得到好处,但必须在未来偿还。软件工程师必须付出额外的时间和精力持续修复之前的妥协所造成的问题及副作用,或是进行重构,把架构改善为最佳实现方式。
二、分类
分成:低级技术债、不可避免的技术债和策略性技术债;
低级技术债:
指团队成员或业务人员不成熟或流程缺陷而导致设计粗糙、工程实践糟糕和测试不足。这些技术债是可以消除的,只要能够提供适当的培训,能够更好地理解技术实践的运用,能够做出合理的业务决策。其具备频繁偶发的本质;
不可避免的技术债,例如:
1 .事前.无法完美预测产品和设计随时间的推移需要如何演进。随着我们完成重要的认识循环并获得经验认知,可能需要修改早期做出的设计和实现决策。
2. 我们在产品中使用的一个第三方组件,该组件的接口随时间的推移而不断发展。他的一些改进引入了新的漏洞等,我们这个曾经让第三方组件很好运行的产品还是欠下了技术债,尽管我们自己没有任何过错。这种债务可以预测(随时间推移而改变组件接口,这样的假设合情合理),但无法避免,因为我们无法预见组件开发人员将来怎样进一步发展该组件。
策略性技术债:
组织从经济角度更好地量化和权衡重要的(往往时效性强)决策;例如:时效性强的产品推向市场;削减初期开发成本,把带有技术债的产品推向市场,等有收益之后再用自筹资金进行后续开发等;
一些常见的技术债:
● 不合适(糟糕)的设计——因为当前所用技术或业务发生重大改变,我们之前曾经有效的设计变得不再适用。
● 缺陷——我们已知但还没有时间解决的软件中的问题。
● 测试覆盖不充分——有些地方我们明明知道该做更多测试却没有做。
● 手工测试过多——实际该做自动化测试的时候我们还在做手工测试。
● 集成和版本管理不善——在做集成和版本管理的时候,采用的方式既费时又容易出错。
● 缺乏平台经验——例如,我们的大型机应用需要用COBOL来写,但身边精通COBOL的程序员却不多。
● 如此等等,技术债这一术语如今已被用于泛指任何一个复杂的问题。
三、后果
1.爆发点不可预期
不可预测的非线性方式增长,不确定哪根是压死骆驼的最后一根稻草。也许就是下一根!
- 交付时间延长
承担技术债意味着现在向未来申请借用工作时间。今天的债务越多,明天的速率就越慢。速率变慢,交付新特性和产品补丁需要的时间也变得更长。
- 缺陷数量巨大
技术债务状况严重的产品变得越来越复杂,因而也更难把事情做对。不同的缺陷盘根错节,以高得惊人的频率造成重大的产品故障。这些故障会对正常的增值开发工作流造成很大的干扰。另外,管理大量缺陷所产生的开销还会影响我们,使我们没有时间开发增值特性。
- 开发和支持成本上升
技术债一增加,开发和支持成本也会开始增加。过去一直简单又便宜,现在却变得复杂且昂贵。在债务状况越来越差的情况下,即使是小改动,也会涉及很高的成本。另外,技术债上升的成本还会影响我们做出继续开发特性还是修复缺陷时的经济决策。在低技术债状况下能够以低成本构建的特性(或要修复的缺陷),在高技术债状况下很可能需要高得多的成本。成本上升会导致产品更不适应其赖以生存的动态环境。
- 产品萎缩
对产品停止增加新特性或修复缺陷使其焕发活力,它对当前或潜在客户就会变得越来越没有吸引力。最后导致产品开始萎缩,不再是大多数客户愿意考虑的方案。仍然在使用产品的人往往也只是暂时接受现实。一旦有机会转到其他产品,他们多半就会转了!
- 可预测性降低
估算不准确,即使是最有经验的团队成员。面对一个负债累累的产品,需要花多少时间才能完成工作,未知数实在太多太多。最后导致的结果是做出承诺并为兑现承诺而建立合理预期的能力被大大削弱,引发不信任;
- 表现越来越差
随着技术债越积越多,人们开始预计工作表现逐渐越变越差,进而降低他们对结果的期望。当然,期望值降低顺着价值链开始蔓延,最终导致组织层面的整体表现越来越差。
- 挫折感四处弥漫
技术债不仅剥夺了技术人员的乐趣,也使业务人员不得开心颜。说得出却做不到的业务承诺,我们还能守多久?我们可怜的客户呢?他们还指望好好用我们这个债务累累的产品干活儿呢!他们很快会厌倦产品故障频频和我们的无能(导致一而再、再而三地出尔反尔)。价值链中曾经有过的信任被沮丧和怨恨取而代之。
- 客户满意度降低
随着挫败感增强,客户的满意度也会下降。因此,技术债伤害的不只是开发团队内部,甚至还包括整个开发部门。更糟糕的是,技术债所造成的后果严重影响到客户及其对我们的看法。
- 起因
前面说过,技术债有三种主要形式,它们的根源各有不同。不可避免的技术债,不管采取什么预防措施,都会积累。低级技术债是团队成员、组织及或过程不成熟所造成的。策略性技术债则是在债务累计收益大大超过债务成本时可能选择承担的债务。
- 如期完工的压力
策略性技术债和低级技术债通常都是迫于业务压力而必须满足某个迫在眉睫的重大最后期限而造成的。
- 试图以错误的方式提高速率
此时此刻,我们需要做出一个业务决策。是希望缩减范围以满足理想的发布日期,还是希望增加更多时间等到可能发布的日期再交付?不幸的是,业务人员往往都会否决这两种选择,而是强令团队必须在理想的发布日期交付所有特性。
按照这种提高的速率工作,团队必须做出慎重的决策,承担技术债(这意味着团队必须走捷径才能足够快速地工作以满足理想的发布日期)。或许设计差强人意,或许某些特定类型的测试(可能是负载测试)会被推迟。结果,积累下技术债。
- 债务积累
旧债如果不还,很快会积累新债。而且,一旦开始出现技术债,就会显示出不良经济后果。
版本2的实际速率比版本1更慢。显然,按照这个开发速率,我们肯定会再次错过目标发布日期。并且,业务人员再一次坚决要求,团队必须在理想的发布日期完成所有特性。结果,我们积累的技术债越来越多。
如果这个模式一直延续下去,速率线最后很可能会变平,表明系统的技术债已经多到使我们的有效速率趋于零的程度。最后造成的后果是我们不敢对产品轻举妄动,因为一处小的改动可能导致18个关联的地方出问题。更糟糕的是,我们根本无法预测哪18个地方会出问题。当然,我们没有什么超级测试框架可以帮助我们判断代码何时出错,但用不着担心,客户肯定会让我们知道的!
- 如何管理
承认:没有哪个产品能做到“无债一身轻”,就像没有哪个产品没有BUG一样;
管理技术债有三个主要活动:
- 管理应计技术债
- 让技术债可见
- 维护/偿还技术债
- 管理应计技术债
- 使用良好的技术实践
指导:简洁设计、测试驱动开发、持续集成、自动化测试和重构等
理解并主动使用这些指导,帮助团队停止向产品增加各种形式的低级技术债务。
- 使用强完成定义
使用Scrum之后,我们希望用一个强完成定义(上表)来指导团队在每个冲刺结束时给出一个低负债或零负债的解决方案。
完成定义检查表中包含的技术细节越多,积累技术债的可能性就越少。弱完成定义所产生的技术债,偿还成本往往都远远高于在冲刺过程中解决问题的成本。没有强完成定义,简直就相当于给技术债积累开绿灯。
- 正确理解技术债经济
要不要负担10万美元技术债来增加45万美元收入呢?
- 让技术债可见
技术债隐喻的主要好处是,能让开发团队和业务人员在同一个情境中进行必要的交谈。为了进行这种交谈,双方都需要技术债的债务状况能够以彼此能够理解的方式呈现出来。
- 业务层面可见
方法:可以从开发速率上来体现对业务的影响;
原本一个迭代可以完成20个故事点,目前只能完成10个故事点
- 技术层面可见
当作缺陷:可以把技术债当作缺陷录入缺陷跟踪系统;
当作任务(PBI):这样做会使重要的技术债与产品列表中的新特性一样醒目。团队通常在技术债偿还成本很高的情况下采取这种方法,而且还要求产品负责人参与决定如何调整它与产品列表中新的增值特性的优先顺序。
- 创建一个特殊的技术债列表,在其中清楚列出每一个技术债。只要产品中发现新的技术债或引入新的技术债,开发团队成员就可以创建一个新的技术债条目并把它加入技术债列表。通过让技术债可见,开发团队不仅可以看到技术债的债务状况,还可以积极主动地计划偿还技术债。还可以利用看板。
- 维护/偿还技术债
1.确定已知技术债是否应该偿还。
2.如果是在编码工作时发现的偶发技术债,就立刻偿还。如果偶发技术债的数量超过某个合理的阈值,清理到阈值附近即可。接着再把未偿还的偶发技术债标识为已知技术债(例如,在技术债列表中创建相应的条目)。
3.每个冲刺都要考虑指定一定数量的已知技术债作为目标技术债,在当前冲刺中偿还。我们倾向于一边做有客户价值的工作,一边偿还高息的已知技术债。
- 偿还技术债的方式
- 并非所有技术债都应该偿还
行将就木的产品、一次性原型和短期产品。
原型的价值不在于代码,而是我们得到的经验认知。原型不是为了市场而设计的,所以可能会欠下一些甚至大量技术债。
短期产品:投票等应用与短期使用的产品
- 应用童子军规则
童子军规则:“离开营地时,要让它比你进去时更干净。”
如果开发团队成员在做某产品领域的相关工作时间,发现了一个问题(偶发技术债),就会清理问题。这么做不只是因为对她自己有好处(这一点毋庸置疑),更是因为这么做对整个开发团队和组织都有好处。
了解决这个问题,团队可以留出一定比例的时间来偿还偶发技术债。一种方法是提高单个PBI的大小估值,为常见的额外技术债预留时间。另一种方法是团队在冲刺计划会上留出一定时间用来偿还偶发技术债。
- 高息技术债优先
比如,有这样一种重要的技术债:一个经常改动的模块,其他有很多代码都依赖它,由于它已经变得越来越难以修改,所以我们迫切需要对它进行重构。我们一直都在为这个债务付息,修改越多,很快就出现债累债的情况。在维护技术债时,我们应该先锁定高息技术债并加以维护。
- 分期偿还技术债
“重构冲刺”识情况而定;冲刺开发具有客户价值的特性,团队选择的不是交付客户价值而是舍本逐末,专门解决本该在每个冲刺逐步解决的技术债。
- 一边做有客户价值的工作,一边偿还技术债
● 将债务削减工作与有客户价值的工作相结合,有利于产品负责人合理安排优先顺序。
● 所有开发团队成员都清楚地知道,减少技术债是大家共同的责任,不得拖延或授权给其他人或其他团队完成。
● 它能强化技术债预防和解除的技能,因为每个人一直都在练习这些技能。
● 它能帮助我们识别出维护债务时需要重点关注的高息区域。最起码能让我们知道修改的代码(或者其他的开发工件)仍然很重要,因为我们还在用它创建新特性。
● 它能避免我们浪费时间清偿实际不必还的技术债。