重构 读书笔记
引言
大家好,今天想聊聊我最近读的一本书——Martin Fowler 的《重构:改善既有代码的设计》。这本书在技术圈真的是经典中的经典,估计很多同学早就看过了。我之前一直拖拖拉拉,最近才终于把它读完,读完后的感觉就是:相见恨晚!
说实话,之前我对“重构”这两个字是有一些误解的。刚开始工作的时候,我觉得重构就是“没事找事”,代码能跑就行了,改来改去干嘛?直到后来接手了一个历史遗留项目,面对着一团乱麻的代码,加一个功能要改七八个文件,我才意识到——原来好的代码和坏的代码,差别真的太大了。今天就把读书的一些收获和体会分享给大家,希望能给还没读过的朋友一点参考。
什么是重构
首先咱们得搞清楚一个问题:到底什么是重构?
按照书里的定义,重构是在不改变代码外在行为的前提下,对代码内部结构进行修改。这句话听起来有点绕,简单来说就是:让代码变得更好,但功能不能变。
举个例子,你有个函数写了 500 行,嵌套七八层if-else,看得人头皮发麻。你把它拆成几个小函数,每个函数只做一件事,逻辑更清晰了,但最终的功能输出是一模一样的——这就是重构。
书里特别强调了一点:重构的目的是让代码更容易理解和修改。不是为了重构而重构,也不是为了炫技。如果你的代码已经很好用了,改了反而可能引入bug,那就没必要动它。
那些让人难受的“代码味道”
读这本书让我最大的收获之一,就是学会了识别“代码味道”(Code Smell)。这个词真的特别形象——有些代码你一看就感觉不对,但又说不上来哪里不对,这就是有“味道”了。
书里列举了很多种代码味道,我挑几个印象最深的来说:
重复代码:同一个逻辑在多个地方出现,改一处要改好几处。这是是最常见的“味道”,也是最容易修复的。 过长的函数:一个函数做了太多事情,几百行代码堆在一起。书里的建议是,一旦超过十几行,就应该考虑拆分了。 过大的类:一个类里属性和方法太多,职责不单一。想想看,如果你要修改一个功能,得去一个几千行的类里找来找去,那得多痛苦。 参数过多:一个函数参数列表老长,调用的时候根本记不住顺序。书里建议超过三四个参数就要考虑是不是该封装成对象了。 发散式变化:一种变化需要修改多个方法,说明这些方法耦合在一起。霰弹式修改:一个变化需要修改多个类,说明职责没有划分清楚。这些“味道”就像代码的预警信号,闻到了就知道——嗯,这块代码可能需要重构一下了。
常用的重构手法
书里介绍了几十种具体的重构手法,我挑几个平时最常用的聊聊。
提取函数(Extract Function):这是我用得最多的。当一个函数太长,或者里面有一段逻辑可以独立出来,就把它拆成新函数。命名很重要,新函数的名字要能说明它做什么。// 之前
function printOwing(invoice) {
let outstanding = 0;
console.log("======");
console.log(" owed: " + outstanding);
// 打印详情...
}
// 重构后
function printOwing(invoice) {
const outstanding = calculateOutstanding(invoice);
printBanner();
printDetails(outstanding);
}
书里对每种手法都讲得很细,包括为什么要这么做、怎么一步步做、可能会遇到什么问题。我觉得最贴心的是,书中给出的例子都是一小步一小步来的,不会让你一次性改太多,这样可以降低出错的风险。
重构和测试的关系
这一点我觉得特别重要,单独拿出来说。
书里反复强调:在进行重构之前,最好先有一套可靠的测试。没有测试的重构,就像在没有安全绳的情况下高空作业——胆子大是挺大的,但万一出问题就完蛋了。
我自己在这方面是有教训的。之前有次重构一段代码,自信满满,觉得逻辑很简单,结果改完上线后发现有个边界情况没考虑到,害得全组人一起加班修bug。从那以后,我重构之前一定会先补测试,确保现有行为被覆盖。
书里推荐的做法是:先写好测试,然后小步重构,每改一步就跑一次测试。这样即使出了问题,也能很快定位到是哪一步引入的。
如果项目本身没有测试怎么办?书里的建议是:先补测试,再重构。或者,至少在重构的关键节点手动验证一下功能是否正常。
我的实践体会
读完这本书后,我在工作中试着应用了一些原则,感受还挺深的。
首先,我开始有意识地控制函数长度。现在写代码的时候,如果一个函数超过四五十行,我就会想能不能拆一拆。拆完之后发现,确实好读很多。
其次,我变得更愿意改名字了。以前觉得变量名、函数名随便取取得了,反正自己能看懂。现在我会花点时间想一个更准确的名字,毕竟代码是写给人看的,多花几秒钟想名字,后续可能节省几分钟甚至几小时的理解时间。
还有就是,我学会了小步迭代。以前总觉得重构要大动干戈,把整个模块推倒重来。其实更好的方式是点点滴滴地改,每次只改一点点,积少成多。这样风险可控,也不会影响正常工作。
当然,有些时候重构的时机也很重要。如果是线上紧急bug要修,那就先别折腾了,先把问题解决再说。重构应该是在日常开发中持续进行的事情,而不是专门抽一段时间“搞重构”。
总结
总的来说,《重构》这本书真的值得一读。它不仅告诉我们什么是重构、怎么重构,更重要的是,它改变了我对代码的态度——代码不是写完就完事了,它是需要持续维护和打磨的。
好的代码是对未来的自己和他人的善意。花了点时间把代码写得更清晰,后续维护的人(包括未来的自己)会感谢你的。
如果你还没读过这本书,强烈推荐找来看看。即使你已经有一定经验,相信也会有新的收获。好啦,今天的分享就到这里,咱们下次再见!
重构 读书笔记
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法