必须移除无用代码

outerspace 8年前
   <p>Kevlin Henney指出,需要发现和移除无用代码。对于编程人员理解程序并采取行动而言,无用代码的存在是一种障碍,因为无用代码存在被唤醒的风险,并会导致严重的问题。移除无用代码并非是一个技术问题,而是一种理念上的和文化上的问题。</p>    <p>Kevlin Henney是一位独立顾问和培训师。他在 2017年欧洲测试大会 上以“我们做事方式中的错误”为题目做了开幕式主题演讲,并在演讲中展示了无用代码的唤醒是如何给企业带来上百万的损失。InfoQ以问答、总结和文章的形式对大会作全程覆盖报道。</p>    <p>软件故障会对个人造成不便也是十分烦人的,还会产生显著的经济和社会影响。Henny展示了数个由于细微的软件故障导致上百万损失的例子。</p>    <p>Henney指出,故障可能源自无用代码。无用代码是存在于系统中的、但并不被认为会再被使用的代码。意外执行这些代码会导致系统严重故障。因此,他建议必须移除无用代码,以避免此类问题的发生。</p>    <p>InfoQ就如何解决无用代码所导致的问题采访了Kevlin Henney,并请教他如何处理出错状态和异常。</p>    <p><strong>InfoQ:您谈及被激活的无用代码将会对企业造成巨大损失,能就此解释一下吗?</strong></p>    <p>Kevlin Henney:2012年8月1日纽约股票交易所开盘后,Knight Capital Group最新的高速算法给出的交易路线错误下单,所产生的交易充斥了整个市场。系统在错误运行大约45分钟并完成了4亿股交易后才被下线。一切尘埃落定后,所造成的净损失达每分钟一千万美元以上。</p>    <p>这个破产界定事件源自于一场完美风暴(即独立发生时没有危险性但一并发生时会带来灾难性后果的事件组合)。为使新的NYSE交易系统按预期在8月1日上线,公司在服务器上部署了更新。工程师手工更新了服务器,但他们并不知道其中的一次部署失败使旧版本保留运行。在新的NYSE交易系统中,他们重用了一个旧标识,但是该停用标识已更改了用途,用于表示另一个意义。虽然该标识在过去的八年中都没有被使用,旧版本代码依然依赖于这个旧标识。</p>    <p>这段已有八年时间处于无用状态的代码由于标识值的更新而被唤醒了。僵尸灾难发生了,只剩下破产一条路。</p>    <p>InfoQ:采取哪些措施本可以避免问题的发生?</p>    <p>Henney:可以说完美风暴中的任何一个贡献因素都是有问题的,但是这些因素的组合被证明会引发更为严重的问题。更改其中任何一个贡献因素都有可能阻止或至少降低损害:</p>    <ul>     <li>服务器是手工更新的:这是一个迫切需要自动化的任务。</li>     <li>失败的更新并未得到关注:没有人去审查更新。飞机舱门虽然是手工上锁的,但飞行安全是通过机组成员间的交叉验证得以提升。</li>     <li>无用代码并非真的无用,除非确实被移除。他们早在几年前就应该移除那些多余代码。</li>     <li>有时确实是出于十分现实的考虑而将标识、记录等改做他用,而非添加新的。但是如果完全可以添加新的而非回收利用,就应该去添加新的。</li>     <li>企业在处理违规交易系统中缺失了上报流程。通常很难预期能得到准确的交易失败情况,但是如果采用高速交易系统意在实现比交易员更快交易的话,很明显这也会导致金钱更快的损失,因为高速交易系统放大了交易能力。企业应该具有清晰的上报流程,最好是具有一种中止机制(Stop-the-line Culture)。</li>     <li>在发生故障的45分钟里,他们在不了解错误原因的情况下将正确的更新进行了回滚。这使得问题更为复杂化,而非解决了问题。一个实时系统不知因何出错,却手忙脚乱地处理,只会让事情变得更糟。不要这样做。</li>     <li>这反映了他们缺少自动化安装,也缺少让系统离线的简单方法。他们应该将“更新”和“紧急停止”都自动化。</li>    </ul>    <p><strong>InfoQ:对于如何处理无用代码,你有哪些建议?</strong></p>    <p>Henney:我的建议就是:“找到他们,删除他们。”</p>    <p>“找到他们”是其中最难的部分。有时无用代码真是难以触及,正如静态分析所给出的。静态分析的有效性虽然取决于所使用的工具、语言和架构,但它是一个很好的解决问题的好出发点。</p>    <p>内幕交易在股票交易中被认为是非法操作,但是在代码里使用内幕知识却是完全可被接受的。开发人员可能对超出需求的代码实现已经有了很好的认识。利用产品特性知识也是完全合法的,当在需求层撤回或替换特性时,关联到这些特性的代码可能也终将退役。</p>    <p>另一条可用线索是代码稳定性。你的版本控制系统是一个关于变更的知识库。代码块的哪一部分从未变更过?很多原因导致代码从未变更,例如:代码已经正确的、代码是无用的或者只是不敢于去更改的。除非开展调查,否则你也不知道原因。当然由于自动重构,无用代码可能仍保持被更改的状态,这些更改也有与其他重构更改相关的签名,但并非是修复软件故障或添加特性。</p>    <p>系统的运行时监控并不能明确指出哪一部分代码是无用的,但可以明确指出哪一部分代码是活的。这有助于缩小搜索范围。</p>    <p>简而言之,就是做假设并进行调查。</p>    <p>删除无用代码并非技术问题,而是思维模式和文化上的问题。人们常会感觉代码如果不做一些事情就没有效果,因此将代码遗留下来也是可以的。需要牢记正是出于同一理由,我们应该移除这样的代码。即如果代码不做任何事情,那么移除它。这个原则可以由版本控制系统替你实现。</p>    <p>移除代码出于很多原因,并非仅是因为存在僵尸灾难的可能性。无用代码使得运行时的资源占用大于所需资源。如果你关心的是性能,那么就要考虑移除无用代码。此外,对于编程人员理解问题并采取行动而言,无用代码也是一个障碍。充斥了无用代码的系统浪费了开发人员的时间,妨害了软件文化,导致代码总处于修改和改进状态。</p>    <p>如果你是因为不确定是否为无用代码而不想移除这些代码,这种不确定性其实是说明了你的架构存在的问题以及它与开发人员之间的关系。</p>    <p><strong>InfoQ:你在演讲中也谈到了关于处理错误的代码的问题。处理错误的代码并非无用代码,但是其中的问题常被忽视并遗留下来。对非致命错误的不正确处理是如何导致灾难性失败的?</strong></p>    <p>Henney:某一部分代码被使用得越多,越可能是发生过缺陷的地方。处理错误的代码通常是系统中最不常被使用的代码,很多错误场景是非常罕见的。因此虽然存在处理各种错误场景的代码,但是代码的正确性并未得到验证。一旦罕见错误场景发生,虽然处理错误的代码在设计上是用于解决错误而非产生新的错误,但是控制流程在导向有问题的执行路径后整个系统就崩溃了。有时毫不夸张的说,就像1996年首次阿丽亚娜火箭失败那样。</p>    <p><strong>InfoQ:对于处理出错状态和异常,您能给出哪些建议?</strong></p>    <p>Henney:我的建议是做审核、静态分析和自动化测试。全面的走查和透彻的讨论有助于找出被疏忽的地方并发现新的问题。你可以从工具中得到一些有用反馈,了解在运行时发生的情况。反馈的内容根据编程语言不同而有所差异。</p>    <p>测试是一种确认在安全环境中执行代码片段的方法,谨记人们在编写处理错误的代码时总会有些盲点和乐观倾向,仅仅去测试正常用例(Happy-Day Scenario)。为解决该问题,时常问一下自己:当发生错误时,相应的处理代码在哪里?对错误条件的测试在哪里?对处理代码的测试在哪里?</p>    <p> </p>    <p> </p>    <p>来自:http://www.infoq.com/cn/news/2017/02/dead-code</p>    <p> </p>