原文地址:Defining and Dealing with Technical Debt
首发:技术债务的定义与处理
我们对"债务"都不陌生吧?这是一个一方(借款人)欠另一方(贷款人)钱的概念,常用于金融领域。比如,我向银行借钱,我就对他们有债务,金额就是他们借给我的钱(加利息!),并且他们期望我还清这些债务。
债务并不总是关于钱,事实上,我们前端开发者经常遇到它,甚至可能不自知。我们称这个术语为技术债务,并将在本文中探讨它的含义。
定义技术债务
我大可以直接让你自己去读技术债务的维基百科,但本文想表达的不止这些。
技术债务是指我们在开发过程中编写代码时所做的妥协的总和。你甚至可以将你编写的每一行代码都视为对技术债务的贡献。这是因为它包括:代码本身、代码的结果,以及代码与其他代码的交互。债务的后果是当需要进行更改时会出现困难。协调"新功能"与"当前代码造成的影响"的难度,与技术债务有很深的联系。
每当我们编写代码时(尤其是如果违反了被认为是最佳实践的规则),我们就开始在所交付的最终产品中看到后果。就像金钱一样,我们在代码中做出的妥协也是可以而且经常需要偿还的,否则,这样的债务会使我们陷入困境,导致难以进行更改。
我们从维基百科了解到,并非所有技术债务都是一样的。实际上,有四种类型的债务需要考虑,下面我们逐条介绍。
鲁莽债务
这些是我们在编写代码时故意而不考虑后果而做出的妥协。这相当于拿了几张银行卡将其刷爆,而没有打算偿还余额。我可没有这样的经验,也决不鼓励这样做。
想想你使用 !important
强制覆盖的次数。通常情况下完全有可能避免使用它,并且通常最好避免使用它。但是,有多少人偶尔在其中加入一个,因为重构之前的代码似乎对我们来说太过艰巨了?这是我们做出的妥协,未来某个时候,当 CSS 有什么奇葩问题时,我们可能不得不处理它。
有时我们知道我们在做鲁莽的事情,有时不知道。命名是一个经典例子,很容易对鲁莽行为视而不见。我们选择的名称(用于函数、类名等)一开始看起来完全没问题,只是在未来发现它以一种意想不到的方式冲突了。这里的鲁莽行为可能是缺乏或不遵循命名策略。
审慎债务
这些是我们明知会在未来看到回报的情况下做出的妥协。你有没有因为借钱进行投资(希望)未来会有回报?这是同样的道理。事实上,审慎通常被认为是一种美德,它表现为对未来的慎重考虑和体贴。
我们如何在代码中做出审慎妥协?想想你曾经写过一些当时看起来无关紧要,但在将来会有意义的东西。我想起了几年前的一些 CSS3 功能。还记得当许多浏览器还不支持圆角时,我们都知道它们很快就会被支持。使用带前缀和不带前缀属性的组合就是一个产生审慎债务的很好的例子:
css
.rounded-corners {
-webkit-border-radius: 5px;
-khtml-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
这是为了支持一个小设计元素而写了很多代码,但我们知道它在浏览器采用这个规范的将来版本中会派上用场。到那时,我们可以自由地通过移除前缀来偿还我们的债务。
(现在,当然,我们有像Autoprefixer这样的工具来处理供应商前缀等问题。)
这种事情仍然是债务。经过思考和努力,产生更多的代码,但也许之后事情不会像你想象的那样发展。(译者注:过度封装也算这一类吧)
故意债务
我们有时会故意在代码中做出妥协,代价便是产生债务。你觉得绝不会这样做,吗?想想一下情况吧:
- 预算限制
- 截止日期
- 最高支付人员的意见(highest paid person's opinion)
我知道最后一个原因至少曾经让我吃过苦头。我们在自己无法控制的情况下妥协,结果产生了技术债务,尽管我们本来是出于好意。
无意债务
这其实是因为不知道自己不知道的结果。这些是我们因为无知而做出的妥协。并非我们有意为之。在这里,命名是相关的例子。例如,我们决定在元素上使用的类名的方式和命名方式可能会对代码的其他部分产生不利影响。这就是为什么我们现在看到有更大的动向来制定命名约定,比如 BEM。
其他例子可能包括:
- 没有考虑函数可能接受的某些边缘情况
- 你只为一个特定的浏览器修复了一个问题,却没有意识到这会破坏另一个浏览器的兼容性
- 你没意识到你使用的库有一个用于某事的方法,于是自己写了一个,甚至发现不如人家的好用
- 你的测试忽视了某些可能发生的用户状态
技术债务的后果
我从未听说过"债务"一词被用来描述积极的事物。相反,它似乎总是会带来负面的后果。对于代码来说,这些后果可能是毁灭性的,表现为代码库不稳定,甚至出现严重问题。
而"利息"这个比喻也是如此。利息是根据我们欠下的债务的金额以及我们应该还清的本金来计算的额外金额。我们写的代码越多,时间越长,利息就越高。一个妥协可能会带来其他问题,造成利息的雪球效应,这些利息最终可能变得无法偿还,表现为维护、性能等方面的问题。
应对技术债务
技术债务就像金融债务一样,我们希望尽量避免它。以下分享一些处理技术债务的方法。
记录一切
在我们的代码中做笔记是一个好习惯,它也可以帮我们摆脱棘手的债务。如果你发现自己需要做出妥协,可以在代码中添加注释来记录它。在这些注释中,解释你做了什么,它可能产生的影响,以及将来如何解决它。你未来自己会感激你的。
当你的注释包含下面的内容,那就特别有效:
- 它为什么这么做
- 与它有关的问题
- 与它相关的其他代码的位置
编码风格指南
保持一个编码风格指南并严格遵守它。编码风格指南将为你的团队或项目提供标准,并帮助你做出一些艰难的决定,比如命名约定或者代码格式。
这两篇代码风格指南可能可以给你需要的信息:
严格遵循的编码风格指南可以减少在长时间未见代码时思考代码的认知负担。
代码审查
尽早、尽可能频繁地审查你的代码。这主题能单独写一篇文章,噢,已经有了。
在进行代码评审时需要对代码进行严格的审查。审查时,你需要判断在可维护性、性能或可访问性等方面是否能做出更好的决策?这一点上代码的作者可能并不是最佳评判者。
耻辱文件
这是我最喜欢的建议之一。Harry Roberts 提出了这个想法,作为一个跟踪故意技术债务的方式。将所有已知的妥协记录在这个文件中,并将其用作需要还清的债务的任务列表。就像一张巨额信用卡账单一样,努力至少每月还清最低还款额。
也许似乎制定技术债务清单是一个不好的主意,但这是已知的技术债务,这总比零散、未记录的、隐秘的技术债务成本低。
总结
本文中我们类比金融中的概念讨论了技术债务。你认为技术债务存在吗?如果存在,你会因何积累最多的债务,又会如何处理它?如果不存在,技术债务是否夸大其词?欢迎在评论中分享你的想法。