如果无暇重构,我们是否应该为遗留代码编写测试方案?

译文
开发 项目管理 测试
编者按:本文主要围绕着“是否应该为遗留代码编写测试方案”进行讨论,一位同事主张“一次性大规模重构”要比多次小规模测试更好的观点,引来多位网友不同的看法。以下是几位网友的回答以及得到不同票数的肯定。欢迎朋友们一起讨论!

编者按:本文主要围绕着“是否应该为遗留代码编写测试方案”进行讨论,一位同事主张“一次性大规模重构”要比多次小规模测试更好的观点,引来多位网友不同的看法。以下是几位网友的回答以及得到不同票数的肯定。欢迎朋友们一起讨论!

[[114058]] 

网友is4发问:

在工作中遇到问题时,我一般倾向于采取《高效处理遗留代码》这本书给出的建议。我会消除代码依赖性,将一部分代码转移到VisibleForTesting公共静态方法及新类当中、从而使这些代码(或者至少是其中的一部分)具备可测试条件。另外,我还会编写测试来确保自己的修改方案或者新功能添加操作不会影响遗留代码的固有效果。

但一位同事对我的作法提出了不同意见。他的观点是:

• 首先,原始代码在新环境下的工作效果可能并不尽如人意。而为其编写测试也许会让日后的修复与修改工作变得更为困难,因为开发人员必须在着手之前先看懂这些测试本身并对其加以修改。

• 如果遗留的GUI代码中包含某种逻辑(例如,~23 lines,2-3 if/else blocks),那么为此编写测试实在无甚价值——毕竟这部分代码的功能根本无足轻重。

• 类似的糟糕状况在代码库的其它部分也可能存在(我是个新人,因此还没见过此类情况);因此通过一次性大规模重构将它们彻底扫清的作法更轻松些。将逻辑提取出来能够消除这部分代码在未来引发麻烦的可能性。

如果我们没有足够的时间对遗留代码进行全面重构,那我是否应该放弃提取可测试部分并为之编写测试的作法?这样做有哪些我没有注意到的弊端?请大家提出自己的意见。

感兴趣的朋友可以点击此处查看关于这个问题的原版表述。

这是种错觉

网友Killian Foth的回答(获得79票支持):

我来说说自己对于这个问题的一点不成熟见解:不编写测试的理由看起来似乎广泛适用,但这其实只是种错觉。

首先,没错,现有代码的确有可能存在错误——但同时它也有可能正确无误。由于相关应用程序整体对于我们来说存在价值(否则我们大可以直接将其抛弃),因此在不具备详细信息的前提下,我们不妨假定其是正确的。“编写测试会让事情更麻烦的原因在于,这样将给整体方案引入更多代码”,这种态度既简单粗暴又站不住脚。

其次,请通过各种手段扩大现有重构、测试以及改进成果的适用范围,从而在实现***价值的同时尽可能缩减需要投入的精力。利用值进行格式设定的GUI方案不该被优先考虑。不过仅仅因为某些内容“非常简单”就放弃对其进行测试也是不科学的。几乎所有严重错误的产生都是因为人们自以为了解真实信息,但实际情况却恰恰相反。

第三点,“我们将在未来一次性进行大规模重构”,这个点子相当不错。通常来讲,就算暂时按兵不动、将来也总有机会对遗留代码进行这样一轮大规模清洗的。但我个人更信奉“稳扎稳打才能赢”的理念。

建立坚实的基础

网友guillaume31的回答(获得34票支持):

我来谈谈自己的几点思考:

当我们对遗留代码进行重构时,自己编写的测试是否会偶尔与理想规范产生冲突其实并不重要。真正重要的是,它们能够切实对程序的当前运行状态作出评估。重构的意义在于通过一系列细微且独立的功能性步骤让代码变得更加简洁;大家肯定不希望在进行重构的同时还要操心漏洞修复工作。而且如果我们在过程中发现了严重漏洞,它也不会随着时间推移而自行消失。我们可以为其编写一套回归测试并暂时将其禁用,或者在自己的待办事宜列表中加中这项漏洞修复任务以待日后处理。一次做一件事,这才叫有条不紊。

我也同意,纯粹的GUI代码很难进行测试,可能也不太符合《高效处理遗留代码》一书中的重构指导方针。但这并不意味着我们应该把与GUI层无关的其它代码同样抛在一边,而不对其进行任何测试。另外需要强调一点,“12 lines, 2-3 if/else block”绝对不能算是无足轻重。任何哪怕涉及一丁点状态逻辑的代码都应该被加以测试。

根据我的个人经验,大规模重构工作难度很高而且效果一般都不好。如果大家不能为自己设定精确而且细化的执行目标,那么整个重构过程很可能陷入无休无止的恶性循环,甚至最终变成像拉住头发把自己提离地面这种根本没有希望的任务。修改的程度越高,破坏原有内容的风险就越大、导致我们陷入失败境地的可能性也将愈发高企。

利用临时性的小规模重构逐步取得进展并不意味着要“破坏未来大规模重构的可能性”,这其实是一种促进手段——即巩固应用程序所依赖的主干与根基。总之,我们应当采取这种步步为营的应对策略。

得不偿失

网友Robbie Dee的回答(获得9票支持):

某些企业的固有文化主张允许开发人员在任何时间对代码进行强化,而非为其提供更为直接的附加价值——也就是新功能。

也许随意发表个人意见有点多此一举,但在我看来这种作法真的有点得不偿失。纯粹、简洁的代码当然能为开发人员带来回报,不过这样的回报实在不够明显。

我个人赞同所谓“童子军原则”(即加入童子军的小朋友需要在‘离开营地前进行清扫活动’),但其他人(正如大家所见)对此往往不以为然。

也就是说,不可知性与技术工作压力会对软件带来不利影响。也许前任开发者时间太过紧张(或者可能是太懒甚至缺乏经验),因此他们也许已经在有限的时间内拿出了虽然存在漏洞但已经是***的设计方案。虽然对这些开发成果进行重构似乎能够收到很好的效果,但同时也可能给原本正常运作的代码带来新的漏洞、甚至进而给用户造成影响。

比较之下,某些改动的风险可能比其它变更更低一些。举例来说,我所面对的方案当中存在大量重复代码,完全可以被安全地从对业务影响很小的子程序中转移出来。

总结来讲,我们必须要在这样的两难选择中作出判断:既要考虑自己未来何时真正着手进行重构,又要确定从零开始编写自动化测试到底能为业务带来哪些切实存在的价值。

译者:核子可乐

英文:Shoud I Write Tests for Legacy Code if There’s No Time for Refactoring

责任编辑:林师授 来源: 51CTO
相关推荐

2022-12-05 10:58:52

2011-05-26 09:26:48

网络设备

2022-07-14 08:16:24

Node.js后端自动化测试

2022-08-02 08:07:24

单元测试代码重构

2015-07-16 11:14:32

云服务DRaaSAWS

2023-02-24 11:29:13

2017-03-13 20:30:23

数据中心服务器虚拟化

2021-10-10 23:02:49

Golang语言代码

2016-11-30 18:35:03

JavaScript

2015-07-16 10:49:56

2013-06-04 09:16:29

Google存储数据

2021-09-26 11:09:57

人工智能AI深度学习

2020-03-09 14:10:48

代码开发工具

2018-05-03 15:34:34

组件测试遗留系统微服务

2015-09-09 10:57:31

数据时代智能产品

2023-09-11 11:05:49

软件开发TDD

2010-07-05 14:47:26

Gartner社交网络

2009-06-29 15:12:00

JNA

2014-04-24 09:52:14

2022-11-04 10:46:40

物联网智能家居
点赞
收藏

51CTO技术栈公众号