重构代码的7个阶段
引言
你是否曾想过重构一个陈旧的模块,但只看了一眼便感到极度不适?文档缺失、函数与类命名奇怪……整个模块就像一个戴着脚镣、衣衫褴褛的人,虽然勉强能走,但状态令人堪忧。面对这种情况,真正的程序员是不会认输的。他们会接受挑战、认真分析,哪怕推倒重写也在所不惜。最终,那个模块会被他们重构,就像以前和大家介绍过的那些令人销魂的编程方式中的“屠宰式编程”一样。
本文译自 The 7 stages of refactoring,以下是重构代码过程中可能经历的七个阶段。
重构的七个阶段
第一阶段——绝望
在你开始查看想要重构的模块时,起初会觉得好像很简单:这里需要改一个类,那里需要改两三个函数,重写几个方法,看上去没什么大不了的,一两天就能搞定。
于是你着手开始重构。当你调整了一些代码,比如修改了命名、修理了逻辑后,渐渐地,你会发现这个“怪物”原来体型如此庞大。你会看到与代码不符甚至含糊不清的注释、完全摸不着头脑的数据结构,还有一些看似不需要的方法却被调用了多次。你甚至无法搞清一个函数调用链上的逻辑。你感到这件事可能一周都搞不定,开始感到绝望。
第二阶段——找最简单的做
你承认你要重构的这个模块就是一个可怕的怪物,不是一两下就可以搞定的。于是你开始着手做一些简单的事,比如重新命名几个函数、移除一些代码阻碍、引入常量来消除魔术数字(Magic Number)等。你知道这样做至少不会让代码变得更糟糕。
第三阶段——再次绝望
接下来的事会让你再次撞墙。你会发现那些代码的瑕疵只是一些不痛不痒的事,改正这些事完全于事无补。你应该做的事就是重写所有的东西,但你却没有时间这么干。这些代码剪不断理还乱,耦合度太高,让你再一次感到绝望。
所以,你只能部分重写那些不会花太多时间的部分,这样至少可以让这些老的代码能被更多地重用。虽然不完美,但是至少可以试试。
第四阶段——开始乐观
在你重构这个模块几天之后,经过不断的迭代,虽然你发现改善代码的进度太慢了,但此时你已知道代码应该要被改成什么样。你在痛苦之后也锁定了那些需要修改的类。是的,虽然你的时间预算已经超支,虽然要干的事比较多,但你还是充满希望,觉得那是值得的。
第五阶段——快速了结
这个时候,你知道你花了太多的时间,你感到自己所面对的情况越来越让你感到不安,你明白自己已经陷入了困境。你原本以为只需要一次简单的重构,然而现在你要面对的是重写所有的东西。
你开始意识到原因是因为你是一个完美主义者,你想让代码变得完美。于是你开始怠慢文档,并找到一个捷径来重写老的代码。你开始采用一些简单而粗暴、快速而有点肮脏的方法。虽然不是很完美,但你就是这样去做了。然后,你开始运行测试做单元测试(UT),发现 UT 报告上全是红色,几乎全都失败了。你恐慌了,于是快速地 Fix 代码,让 UT 能工作。此时,你拍拍自己胸口说到:“没问题。”于是把代码提交了。
第六阶段——修改大量的 Bug
你的重写并不完美,虽然其过了测试,但是那些测试对于你的新代码有点不太合适。虽然它们都没有报错,但是测试的范围太小了,没有覆盖到所有的情况和边界。
所以,在这以后,你还需要几周的时间不得不来修改越来越多的 Bug,这使得你的设计在每一次 Quick-fix 后就变得越来越难看。此时,代码已经不像你所期望的那样完美了,但你依然觉得它还是比一开始要好一些。这个阶段可能历经几个月。
第七阶段——觉悟
经过了 6 个月,你重写的模块又出了一个比较严重的 Bug,这让你重构的那个模块变得更难堪。你发现出的这个问题是和当初的设计不一致,你还发现被你重构掉的那段老的代码并不是当初看上去的那么坏,那段老的代码确实考虑到了一些你未曾考虑到的事情。
这个时候,你团队里有人站出来说这个模块应该被重构或是重写,而你却不动声色地一言不发,并希望那个站出来的人能在几个月后能觉悟起来。
结语与反思
不知道这是不是你的经历,我经历过很多次这样的事。对于很多维护性质的项目,我几乎不敢动,哪怕看到代码很不合口味。
那些从来没有写过代码的敏捷咨询师一定会说用 TDD 或是 UT 可以让你的重构更有效也更容易。但我想告诉你,这种脱离实际的说法很不负责任。这就好比说——我在杀猪的时候遇到了一些麻烦,因为我对猪的生理结构不清楚,或是这本来就是一头畸形的猪,导致我杀的猪很难看;而伟大的敏捷咨询师却告诉我,要用一把更快更漂亮的刀。
软件开发永远不是那么简单的事,杀猪也一样。
说明:本文译文源自 2011 年的博客文章,文中提到的部分观点与术语(如敏捷咨询、UT 流程等)带有当时的时代背景,但重构过程中遇到的心理阶段与技术债务问题在当今软件开发中依然具有普遍的参考意义。
版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
本文地址:https://1diff.fun/archives/zhong-gou-dai-ma-de-7-ge-jie-duan.html
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。