大话重构连载12:你不能没有保险索

通过前面的描述你已经对重构中“小步快跑”的开发模式有了一个清楚的认识。学会和习惯小步快跑的开发模式,对于重构工作极其重要,因为它让这种大范围、大幅度修改代码的重构工作变得不再像以往那样让人胆战心惊。究其原因,虽然从结果上是在大范围、大幅度调整,但每一步却是小范围、小福度调整,并且能保证每一步都是正确的。

然而,这里有一个非常重要的假设条件,那就是“保证每一步都是正确的”,这是怎么保证的呢?就这个问题,我们需要展开来认真讨论讨论。

毫无疑问,系统重构就其结果来看,是在对软件系统进行大范围、大幅度的改动,而这种改动过去我们是无法想象的,因为它实在是改动太大了,一不小心就会产生一个毁灭性的结果。这就是许多人不敢轻易尝试系统重构的重要原因。

是的,这就是真相,如果你不能正确地验证每一步系统重构是否正确,或者你的验证方式存在缺陷,即使小步快跑也不能解决重构带来的风险。所以我们说,系统重构,你不能没有保险索。这个保险索就是每次重构后正确的测试方法。

什么是程序代码正确的测试方法,其在不同的场景中标准是不一样的。但与其它测试不同,系统重构在测试代码正确性方面却有自己独特的方法。系统重构,从自身的定义上就把其代码正确性的验证方式描述得十分明白,那就是“不改变软件外部行为”。

“不改变软件外部行为”,我们可以从多个层面上看待这个问题。首先从功能层面上看,重构前系统提供给用户什么样的功能,重构后也应当提供同样的功能。说得更加具体一些,重构前,用户从界面上输入什么内容,发出什么请求,得到什么结果,那么重构后用户应当得到同样的结果。这种结果可能体现在前端界面所展现的结果中,也可能体现在此处操作后存入数据库的数据中,即重构前后系统存入数据库的数据也应当是一致的。存入数据库的数据同样是测试中系统输出的一种。

从功能层面再往下钻就到了代码层面。打开我们的软件系统,有各个层次、各项接口和各种函数。我们进行系统重构往往是在某个层次、某项接口或某个函数上进行的重构。比如,我们对某项接口进行重构,那么我们可能会修改这个接口的实现类、方法函数、底层调用类,但不论怎么修改,这个接口必须保持不变。也就是说,我们代码层面的重构,“不改变软件外部行为”是针对的这个接口。你可以重构接口内部,但必须保证接口外部是不变的。

所以,系统重构的测试可以从两个层面来进行:系统测试与单元测试。系统测试往往是一种手工测试,当然也可以使用QTP等工具进行一些简单的录制。重构前我们首先通过需求文档确认系统现有功能,根据现有功能设计测试用例。然后进入系统,确保每个测试通过,并录制成QTP脚本。这样,我们对重构的准备工作就完成了。在整个测试过程中,我们每完成一次重构就去手工执行这些测试,或者执行QTP脚本,保证每个测试通过。如果测试不通过,则要么寻找问题原因并解决,要么就恢复到上次测试的版本,此次重构宣布失败。

反复地手工进行同样的测试是一件比较烦人的事,因此你可以有两个选择:录制QTP脚本,以及在接口层面建立自动化测试程序。这里所说的自动化测试程序是指那些基于JUnit编写的自动化测试程序,它实际上是在代码层面进行的单元测试。建立自动化测试的关键在于我们在哪个层面建立测试。代码有许多层次,有函数级别、有类级别、有接口或抽象类级别,从系统分层结构来说有底层、DAO层、BUS层、Web层。每次重构都是站在某个层次进行重构,因此自动化测试代码也应当在这个层次上写。比如最初的重构是在函数层次上进行的,就应当对函数写测试代码;后来在对象层次上进行重构,就对对象写测试代码;再到接口层次……

与手工测试一样,在系统重构前,我们首先保证原有代码自动化测试通过。然后执行重构,保证每次重构都能够测试通过,如此往复。但重构中的自动化测试有一个问题就是,测试接口不太稳定。起初是在函数级别进行的重构,我们写了针对函数的测试代码。但随着重构的深入,我们开始在对象层面进行重构了,我们可能要调整原有的函数。这时将意味着原有的针对函数编写的测试代码将失效而必须要遗弃,这不得不说是一种浪费。因此我给大家的建议是,不要过早编写自动化测试代码,它不一定能节省我们的时间,甚至可能花费更多。最初的重构可以采用手工测试或QTP测试的方式进行。

大话重构连载首页:http://blog.csdn.net/mooodo/article/details/32083021

特别说明:希望网友们在转载本文时,应当注明作者或出处,以示对作者的尊重,谢谢!

时间: 2024-10-12 04:42:36

大话重构连载12:你不能没有保险索的相关文章

大话重构连载3:在保险索上走钢丝

当我们开始系统重构的时候,不是着手去修改代码,而是首先建立测试机制.不论什么程序,只要是被我们修改了,理论上就可能引入BUG,因此我们就必须要进行测试.既然是测试就必须要有一个正确与否的评判标准.以往的测试,其评判的标准就是是否满足业务需求.因此,测试人员往往总是拿着需求文档测试系统. 与以往的代码修改不同,重构没有引入任何新的需求,系统原来什么功能,重构以后还是这些功能.因此,重构的测试标准就只有一个,就是与之前的功能完全保持一致,仅此而已. 然而在许多经典的重构书籍中,大师们总是建议我们首先

大话重构连载首页

<大话重构>这本书是我写的第一本书,从今天起我将通过连载的形式逐渐跟大家分享. 这本书让你: 告别游击队转变为正规军. 远离劣质代码走向精妙设计 真正明确专业级的软件开发是如何的 真正明确重构是如何一步一步进行的 高效重构七步曲.面对实践不卡壳 让遗留系统维护不再是你的梦魇 读完这本书以后: 需求变更不再纠结.重构让你润物细无声地容纳它们 超越代码级的重构,从各个层面深度领略重构之美 自己主动化測试不再是梦想.重构让自己主动化測试走你 又一次审视熟悉而陌生的技术.将碎了一地的它们又一次铆合在一

大话重构连载8:盘点我们的重构工具箱

下面我们来盘点一下系统重构工具箱里都有什么,也就是看一看系统重构到底都有哪些方法.系统重构总是在不同层次上调整我们的代码,因此重构方法也就分为了多个层次.从总体上看,重构方法分为以下几个层次:方法的重构.对象的重构.对象间的重构.继承体系间的重构.组织数据的重构与体系架构的重构. 前面那个例子我们可以清楚地看到方法的重构过程.方法的重构往往发生在一个对象的内部,是对一个对象内部的优化.从这个例子中,我们首先看到了增加注释.调整顺序.重命名变量.进行分段等操作,这些虽然不是什么重构方法,却是我们进

大话重构连载16:超级大函数

事情总是这样的:当我们对一个遗留系统一忍再忍,再忍,忍,还要忍--终于积攒到某一天,实在忍无可忍了,拍案而起,不能再忍了,重构!!!事情就这样发生了.然而,在这时你突然发现,重构的工作千头万绪,真不知从何开始.堆积如山的问题此起彼伏,期望修改的设计思绪万千.这里有个想法,那里有个思路,什么都想做,却什么都做不了,真是脑子里一团乱麻.这时候,没有一个合理的步骤,清晰的计划,瞎干蛮干是十分危险的,它会为你的重构带来不可预期的未来.无数次的经验告诉我,不论是什么系统,采用什么架构,从分解大函数开始,肯

大话重构连载7:重构是一系列的等量变换

系统重构要求我们对代码的每一步修改,都不能改变软件的外部行为,因此在系统重构中的所有方法,都是一种代码的等量变换.重构的过程,就好像在做数学题,一步一步地进行算式的等量变换.经过一系列等量变换,最终的结果虽然在形式上与原式不一样,但通过计算可以得到与原式完全相同的结果. 这种等量变换对于重构来说非常重要,它使得我们进行重构以后,程序还是那些程序,代码还是那些代码.但是,等量变换不等于原地踏步.正如矩阵通过等量变换可以得到方程组的解,微积分可以通过等量变换计算最终的结果,重构通过等量变换,在保证代

大话重构连载14:我们是这样自动化测试的

说了那么多,让我们用示例看看,系统重构是应该怎样做自动化测试的.还是回到前面那个HelloWorld的例子(详见 3.3 小步快跑是这样玩的),该类中有一个sayHello()方法,只要我们输入当前的时间与用户名,就返回对该用户的问候语.如果当前时间是上午,则返回"Hi, XXX. Good morning!":如果是下午,则返回"Hi, XXX. Good afternoon!":如果是晚上,则返回"Hi, XXX.Good Night!",这

大话重构连载11:小步快跑是这样玩的

说了那么多.相信你对小步快跑的概念有了一个初步的印象,但理解还不是非常深.让我们来看一看一个实际工作中的样例,来亲身感受一下什么是大布局,什么是大设计.什么是小设计. 还是回到前面那个HelloWorld的样例,起初的需求总是简单而清晰的. 当用户登录一个站点时,站点往往须要给用户打一个招呼:"hi, XXX! ".同一时候,假设此时是上午则显示"Good morning! ",假设是下午则显示"Good afternoon! ",除此显示&qu

大话重构连载15:采用Mock技术完成测试

第五次重构我们引入了数据库的设计,用户信息要从数据库中读取,问候语库存储在数据库中,并支持添加与更新.数据库的引入使自动化测试变得困难了,因为数据状态总是变化着的,而这种变化使得测试过程不能复现,这是我们不愿看到的.因此,我们在设计时将业务与数据库访问分离,形成了UserDao与GreetingRuleDao.此时,我们的设计应当遵从“依赖反转”原则,即将UserDao与GreetingRuleDao设计成接口,并编写它们的实现UserDaoImpl与GreetingRuleDaoImpl.这样

大话重构连载17:抽取方法的实践

说了那么多理论,我们来看看怎样使用抽取方法来重构遗留系统.如前所述,重构的过程首先是阅读程序代码,边阅读边整理程序.将功能相对独立的代码段放在一起,在前面加上注释.调整一些程序的顺序,将相关的代码尽量放在一起,但要保证程序执行的结果不会发生改变.比较典型的,将变量的定义与使用变量的代码放在一起.这个步骤比较实用,因为许多的遗留系统,其代码都有一个坏毛病,就是在程序开始时定义一大堆变量,但要弄清这些变量都用来做什么,却十分困难.边读边调整,将变量的定义逐渐迁移到使用它的代码段中,将大大提高代码可读