消除技术债务?DevOps可以这么用!

DevOps强调开发运维过程的可度量与透明化。而通常情况下我们把软件质量分为内部质量和外部质量。所以我们应该对内部质量和外部质量分别进行度量,以便持续改进和优化软件质量。

软件的内部质量通常指代码和设计的质量。内部质量可以通过应用设计和编程达到最佳实践,也可以通过持续一致的开发和交付流程来提高。

通常,软件的外部质量是通过查看和使用软件(例如验收测试)来度量的。

比较常见的情况是,有的软件外部质量很好(所有功能都能正常使用),但是内部质量却很差(可能有糟糕的代码、不可维护的代码)。从长远的角度看,内部质量不佳最终会影响外部质量。应用程序会持续不断地冒出新的bug,而且开发时间会由于“技术债务”的增加而变长。

1技术债务的形成 

技术债务类似于金融债务,它也会产生利息。由于初始鲁莽的设计决策,在未来的开发中我们需要付出更多努力,消耗更多的时间。我们可以选择继续支付“利息”,也可以通过重构设计来将一次付清本金。虽然一次性付清本金需要付出一定的代价,但这样可以降低未来的利息。

1、鸡和蛋的故事

有人用下面这个的故事形象地描述了技术债务的形成过程:

有一个农民,他有三只鸡,每只鸡每天生一个蛋。农民与当地的杂货店有生意来往,杂货店老板每天从农民那里买两个鸡蛋,放在店里售卖。一切都有条不紊地进行着,直到有一天杂货店老板突然出现在农民的家门口。

老板:老王,吃饭了吗。

农民:呀,刘老板,你怎么来了。你看,我刚吃完饭,正准备给你送鸡蛋呢。有什么事还麻烦你亲自跑一趟?

老板:今天我来是想要拿一些鸡肉的。

农民:肉吗?这个我们合同里没写呀。

老板:我知道,但我确实需要鸡肉啊。最近生意做得好,我就琢磨着可以搞一个企业家禽服务平台。

农民:啥?

老板:就是给一些重要人物提供新的商品。总之,我现在等着要鸡肉,你能给我一些吗?

农民:刘老板,这事没你想的那么容易啊。你看,我必须孵化鸡蛋,然后把小鸡养大。估摸着也要一个月。

老板:一个月?太久了…我现在就要。

农民:这个我也没办法,我们没法违背自然规律啊。

老板:你杀一只鸡就阔以了嘛。这样一来,我能拿到肉,你每天还是能拿到两个蛋。说起来,你每天也只要两个呀。你自己算算这笔帐。

农民:可是这样一来如果有一只鸡病了死了,那我咋办啊,我可给不了你两个鸡蛋了。

老板:(催眠)你不相信我老刘吗,不会有什么事情发生的。我需要肉,这事十万火急!你就给我吧。

农民:行吧…

说完,农民拿起屠刀将一只鸡送上了天堂。

杂货店老板开心地拿着肉回到了店里。

过几天杂货店老板又来了。

老板:老王啊,我告诉你一个好消息。上次那个鸡肉一下子就抢空了,太受欢迎了。快快快,再给我一只鸡。我们大赚一笔。

农民:可是刘老板,再给你一只鸡,我每天就没法给你两个鸡蛋了。

老板:哎呀,别管那么多。客户想要肉,已经下订单了。

农民:不行不行,这合同里写了,我每天要给你两个鸡蛋。你这不是要我违约吗。

老板:但是我特别,特别,特别需要肉!就在明天!否则客户会生气,地球会毁灭!给我一只鸡,现在!

农民:那你拿走吧!但是我要再提醒你一次,从现在开始,每天没有两个蛋了。

老板:晓得,晓得。但是你脑瓜子好使,肯定有办法。

杂货店老板满意地走了。

然而,一天后...

老板:老王,怎么每天只有一个鸡蛋?

农民:你问我?我有三只鸡,你拿走了两只,现在,这里只有一只鸡。一只鸡每天只能下一个蛋。

老板:合同规定的条款就摆在这里。你每天要给我两个鸡蛋!现在你要我怎么向客户解释?

农民:老板啊,问题出在鸡身上,这逼死我也没有办法啊。

老板:好吧,好吧。算了,说点别的吧…我想哈,不然我再拿一些肉吧。

2、技术债务的分类

Steve McConnell将技术债务分为两类:

  • 无意识的 - 由于经验的缺乏导致初级开发者编写了质量低劣的代码。
  • 有意识的 - 团队根据当前而非未来进行设计选型,这种方式能很快解决当前的问题,但却很拙劣。

Martin则将技术债务划分为4个象限:

(1) 不计后果,有意识的。团队没有时间做设计,匆忙给出了一个的方案,缺乏对质量的预见。

(2) 谨慎,有意识的。尽管有很多已知的缺陷,但团队必须现在交付产品。团队对此造成的后果心中有数。

(3) 不计后果,无意识的。团队压根就不知道基本的设计原则,更不用说引入的“坏味道”了。

(4) 谨慎,无意识的。拥有优秀设计师的团队很容易遇到这种情况。他们交付的方案具有商业价值,但在完成方案后才明白什么才是最好的方案。

实际情景中项目的技术债务问题是不可避免的。问题的关键是,千万不能引入不计后果的债务,因为它会持续不断地产生“坏味道”,而且也很难对付。

2技术债务与质量投资 

技术债务的主要问题是它通常只代表了系统的内部质量,而质量有哪些影响并不明确。特别值得注意的是,技术债务的经济影响无法简单地表现出来。很奇怪一点是,如果这些代码不需要修改,那技术债务就完全没影响。但是,一旦要修改这些代码,技术债务就成为代码的重要属性。所以,技术债务很可能对项目的成功与否、外部质量完全没有影响。

因此业界有人提出,不要单纯强调技术债务的重要性,如果要想通过DevOps消除技术债务,让开发有效地处理掉技术债务,建议使用“质量投资”的概念。

使用质量投资,处理技术债务就有可能获得利润。使用财务概念积极地管理代码质量,可以很容易决定哪些质量问题应该立即解决,哪些可以暂时接受。

假设我们有一个系统,它包括三个模块:客户、订单和发票。客户管理是个非常老的模块,已经不再开发了。因此,这个模块不适合做质量投资。因为仅当代码被修改时才会产生修复成本。而在这个例子中,修改的可能性为0。因此支付任何修复成本都将导致损失。

然而,我们知道在接下来的迭代中,对订单流程进行了大量修改。根据经验,发票管理也必须进行一些修改。因此接下来就要重点评估订单模块和发票模块的质量问题。订单管理的测试覆盖率非常低,客户管理的代码非常复杂,也就是说方法和类有大量的代码,并且有很多复杂的循环。

我们来评估一下修复成本和非修复成本。非修复成本的评估也应考虑模块修改的可能性。在下一个迭代中,如果代码质量相同,订单管理估计要投入20天。而如果测试覆盖率能提高,那么估计只需投入13天。因此,非修复成本是7天。这非常高,因为质量确实太差了,同时也因为有大量代码要修改。

  • 订单管理:很低的测试覆盖率,修复成本:5天,非修复成本:7天。
  • 发票模块:很高的复杂度,修复成本:5天,非修复成本:4天。

这些评估表明订单模块的质量投资产生了2天(=7天-5天)的利润。相反,发票模块的质量投资没有利润,甚至会导致亏损。由此可见,投资当前的订单系统是有价值的。因为根据团队的评估,提高测试覆盖率就有利润。对于发票模块,情况并不明确。就现在来说,其质量投资没有利润。然而,发票模块很可能在未来的几个迭代中也需要修改。这样你就能从发票模块的质量投资中得到利润。

根据给出的评估和计算出的利润,也可以为每个质量投资推算出投资回报率(ROI)。投资回报率表示相应的成本产生了多少利润。因此,投资回报率等于利润除以修复成本。订单模块质量投资的投资回报率大约是40%(=2天/5天)。我们通常会寻找机会去获取比较高的投资回报率,使用这些财务术语,我们可以看到代码质量提高后的收益。当然,这些数字都是估计值。然而,在这种做法下,团队不只是从基于自己的原因寻求质量的提高,更重要的是由于经济原因。我们也可以在迭代计划中更有效地对技术债务消除的工作任务项进行选择和排序。

3技术债务处理方法 

虽然质量投资的表达方式有利于开发团队出于经济原因考虑技术债务的消减。但是,我们在实际操作过程中发现,尤其是在传统IT领域,技术债务消减仍然显得动力不足。

在某电信运营商的DevOps平台规划建设实践过程中,我们提出“基于持续集成,内部质量透明化 + 外部质量验收驱动”的方法,对技术债务进行消减处理。

1、外部质量验收驱动

技术债务的形成往往是由于赶进度忽略了非功能质量特性而导致的,由于内部质量的不佳(设计或代码质量不高)导致外部质量的低下。传统IT领域通常有上线前的验收测试,如果能够在验收测试过程中重点关注非功能需求的实现质量,则可以“由外而内”地驱动开发团队在开发过程中重视和改善软件系统的内部质量。

按照某电信运营商的《业务支撑网非功能需求管理办法》,把非功能需求体系划分为:

• 性能

• 可靠性

• 可维护性

• 可监控性

• 安全性

并且制定了相应的验收标准。早期由于缺乏细化的入网验收执行规范和相应的资源投入,管理办法和验收标准成了一纸空文。目前,我们逐渐加大了资源投入,组建了相应的入网验收测试团队,制定了性能基线管理、安全基线管理等持续长效的质量管控机制,向非功能需求的规范化管理目标逐渐迈进。

这种“自后而前,由外而内”的方式可以驱动开发重视和改善软件系统的内部质量,在迭代计划中加入技术债务消减工作任务项,从而改善软件系统的外部质量。这也是DevOps强调的“运维前移”实践。

2、内部质量透明化

开发之所以做出忽略内部质量,不理会技术债务的选择。除了进度压力、缺乏经济驱动力的原因之外,还有一点是:缺乏内部质量数据化的管理与技术债务发展趋势的透明化展示。

在我们所规划的DevOps平台中,会借助一些代码分析工具,把代码设计的“臭味道”嗅探出来,例如,当我们的软件出现下面一种“气味”时,可以表明我们的软件正在“腐化”:

僵化性:很难对系统进行改动,因为每个改动都会迫使对系统许多其他部分的改动。

脆弱性:对系统的改动会导致系统中和改动的地方在概念上无关的许多地方出现问题。

牢固性:很难解开系统的纠结,使之成为一些可以在其他系统中重用的组件。

粘带性:做正确的事情要比做错误的事情要困难些。

不必要的复杂性:设计中包含有不具任何直接好处的基础结构。

不必要的重复:设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一。

晦涩性:很难阅读,理解,没有很好的表现出意图。

而这些代码的“坏味道”,通过JavaNCSS、CheckStyle、PMD等工具,都可以找出来并进行数值度量。通过这种方式,我们可以观察代码设计内部质量的变化趋势,及时提醒开发注意技术债务的积累,并及时修正和优化,从而防止情况恶化。这就好比健康监控,在量变达到质变之前,及时进行治疗。

3、基于持续集成的技术债务消减

在实践中,我们发现可以通过很多不同的维度评价代码设计的内部质量,借助工具也能度量出很多方面的数值。如果单单拿一个值来作为质量控制的阀值不是很科学,因为业界也缺乏一定的标准可参考。而且每个软件系统的业务、架构,甚至编程语言都不一样,很难有一个统一的标准阀值。

例如,对于代码复杂度的度量,业界通常用圈复杂度。IBM的某些数据调查也表明圈复杂度超过10的代码就会比较复杂、容易出错、不易维护。但是具体到某些项目,我们还是比较难定义这个阀值,是不是圈复杂度超过10的方法就一定要修改呢?

实践中我们认为不一定。例如某电信运营去中心化项目中,对于由老CRM代码切过来的新项目代码,在进度压力下,很多代码重构的工作量比较大,某些核心业务逻辑算法本身就比较复杂。在这种情况下,如果一刀切地要求圈复杂度超过10的方法就必须修改,否则不能签入代码,就未免太简单粗暴,可操作性也不强。

我们的处理办法是:基于持续集成的代码构建和自动化分析,在一段时间内,观察代码复杂度的变化趋势。首先确保新加入的代码不能超过一定的阀值。其次,确保对老CRM代码的修改后,代码复杂度保持原有水平,尽量下降。最后,要求在若干次迭代版本后,代码复杂度下降幅度要达到30%。

另外,对于复杂度偏高的代码,同时做出单元测试覆盖率的要求,例如分支覆盖100%。

关注变化趋势,而不是单一的一个阀值。这样,开发关注技术债务的积累过程,在早期就能做出技术债务消减的处理计划并持续实施。在这个过程中,Sonar质量度量平台可以帮助我们实现代码设计质量的持续监控,包括对代码复杂度、重复度、代码规范吻合度的监控等。

借助Sonar定义“质量门”,进行技术债务的预警,提醒开发人员及时处理技术债务。

并且,在趋势发展上可以给出直观的数据参考。帮助开发团队制定技术债务消减计划。

4小结 

本文首先通过分析技术债务的形成过程,细分了技术债务的类型。然后从外部质量和内部质量的角度分析了技术债务处理的可行办法。最后提出方法:1、通过外部质量验收驱动技术债务消减。2、内部质量透明化,基于持续集成度量技术债务发展趋势。这样可以促进技术债务的及时处理,从而提高软件系统的总体开发运维效益,实现DevOps战略在传统IT领域的实施落地。

作者介绍:陈能技

 

 

  • 2016全球敏捷运维峰会特邀嘉宾。
  • 【DBA+社群】专家,新炬网络首席APM架构师。
  • 14年开发测试与质量架构经验,擅长DevOps及APM、Docker、持续集成、持续交付在企业中的落地实施。
  • 著有《软件性能测试诊断分析与优化》、《软件自动化测试成功之道》、《深入浅出性能测试与LoadRunner实战》等书。 

本文来自合作伙伴"DBAplus",原文发布时间:2016-02-19

时间: 2024-10-30 22:17:54

消除技术债务?DevOps可以这么用!的相关文章

投资于质量 不再有技术债务

一个童话故事 很久以前,有个软件开发团队找到他们的经理."我们的项目有相当多的技术债务(Technical Debt),我们应该做点什么."这个团队说.他们展示了一张图(图1)来说明项目的技术债务."技术债务关系到项目质量."他们说.并展示了技术债务各部分的分解,通过静态代码分析,能发现过于复杂的代码.重复的代码和冲突."我们需要去除技术债务"他们告诉经理. 图1:SonarQube技术债务插件的结果报告 但经理困惑了:什么是技术债务?他该额外再

Habya'a(临时拼凑的组件)与技术债务

我们曾遇到过最后期限即将到来.时间非常紧迫的情况.当时,我们必须尽快修复Bug,然而其中的一个Bug特别坚韧,任我们百般努力也无可奈何!随后,我的某个同事接手了调试工作.他强行写入了一些应该从数据库中检索来获取的值--它们在系统运营的最初几个月里不会发生变化--随后--系统神奇地正常工作了! 对于这类"莫名其妙的代码",我的这位同事以非常风趣的埃及俚语称之为"Habya'a",意即临时拼凑的组件. 我同事和他的创造性俚语相仿,Ward Cunningham在1992

VoIP技术之回声消除技术

"在PBX或局用交换机侧,有少量电能未被充分转换而且沿原路返回,形成回声.如果打电话者离PBX或交换机不远,回声返回很快,人耳听不出来,这种情况下无关紧要.但是当回声返回时间超过10ms时,人耳就可听到明显的回声了.为了防止回声,一般需要回声消除技术,在处理器中有特殊的软件代码监听回声信号,并将它从听话人的语音信号中消除.对于IP电话设备,回声消除技术是十分重要的,因为一般IP网络的时延很容易就达到40-50ms. " 一. 因特网语音通信中回声的特点 与传统电话相比,因特网上进行语音

Docker在云平台上的最佳实践:基于容器技术的DevOps探索

12月9日,在云栖计算之旅线下沙龙上,阿里云容器服务团队的高级研发工程师秦妤嘉分享了<基于容器技术的DevOps探索>.首先介绍了DevOps和CD,接着分析了Docker如何打破传统CD壁垒,最后讲解了怎样从零开始搭建一个持续交付系统. 视频回顾 DevOps与Continuous Delivery DevOps 在一个较成熟的软件和服务交付的团队里,就技术层面来说主要分为三个组成部分:开发.测试和运维.开发测试团队比较关注的是代码能否运行,而运维比较关注的是系统能否在上线后稳定运行,于是隔

机器学习中的技术债务

许多人遇到技术债务时都会眉头紧锁,但一般来说,技术债务并不是一件坏事.例如,当我们需要在最后期限之前发布版本的时候,技术债务就是一个可以利用起来的合理手段.但是技术债务存在与金融债务一样的问题,那就是到了要偿还债务的时候,我们所付出的要比开始时付出得多.这是因为技术债务具有复合效应. 经验丰富的团队知道应该在什么时候偿还成堆的债务,但机器学习中的技术债务堆积起来却非常迅速.你可能在一天之内欠下价值数月的债务,即使是最有经验的团队也可能因为一时的疏忽而产生巨额债务,使得他们需要耗费半年才能恢复,这

技术债务(母鸡的遭遇)(转)

技术债务,是指匆忙的实现一个功能,却对现有的程序库造成了破坏(在实现的过程中污染了代码库的设计),这对于一些项目经理/客户来说就像是天书奇谈.也许他们是明白的,只是不愿意承认罢了,我估计是这样的.不管怎样,我想起来一个小故事,当下次遇到这种情况,需要向他们解释增加某些新功能的代价时,也可用讲这个故事给他们听. 一个农夫有3只母鸡.每只母鸡每天下一个蛋.农夫跟当地的一个食品店老板做生意.食品店老板每天从农夫那里买2给鸡蛋放在店里出售.一切都很好,直到有一天,食品店老板出现在农夫家里: 食品店老板:

技术债务管理以及Firefox/Chromium的债务评价

现在的软件开发是在遍地敏捷,人人讲唯快不破的时代,哪有人有时间思考代码质量,设计的质量? 哪个又不是从一堆代码中杀出血路来实现另一个功能?一个产品都存活不了几年,何必考虑什么可维护性? 我们追求进度的时候,总是要牺牲些东西,或是破坏了一些东西等着后面补.这就是技术债! 管理不好,债台高筑,即使不破产,也是要拆东墙,补西墙的玩平衡.现实是残酷的,但不影响我们抬头看看这个世界. 技术债务 技术债务(Technical Debt)这个词,我最早是从InfoQ关于Uber的一个访谈中了解到的,正好也在思

2016 只剩最后一个月 你的 &quot;技术债务&quot; 还清了吗?

一夜醒来,猛然发现,2016 已经只剩最后一个月了! 回忆过去的 330 多个日与夜,哪些互联网圈的大事让你瞠目结舌? 也许是 AlphaGo 在堪称人脑游戏巅峰的围棋领域屡战告捷: 也许是 Pokémon Go 称霸大洋彼岸,虚拟游戏与现实场景没有了界限: 也许是双十一的天猫,用 20 秒的时间,实现了"挣它一个亿"的小目标: 也许是美帝的黑客,用网络技术,把即将坐上总统交椅的希拉里掀翻在地: -- 当然了,以上可能都看起来与你无关.但是这一年你一定真切地感受到了这些-- 我们曾立志

[Android]使用MVP解决技术债务(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5892671.html 使用MVP解决技术债务 原文:https://medium.com/picnic-engineering/tackling-technical-debt-with-mvp-67e805ed5103#.couu0d5i0 免责申明:这篇博客并不是讲关于怎么使用MVP的方式(上帝知道关于这些已经太多了)去写Android代码.而仅仅是我的个人