今天来聊一聊软件开发领域,经常被提及和讨论的话题:重构。
一、什么是重构
重构是指:重组现有代码实体、改变其内部结构而不改变其外部行为的规范式技术。
二、重构有哪些特点
一般来说,重构有以下几个特点:
- 重构是有规范的,不应随意为之;
- 重构 不应导致外部行为改变;
- 重构是一项日复一日的工作,需要采取 低风险的小步骤 进行,不是对代码库进行自由的、大规模的重写。
三、什么时候重构
通常来说,当你学到一些新东西时,你就应该重构。
哪怕只是过去了十分钟,只要你确定现在的你比十分钟前的你更了解某件事情,你都应该考虑重构。
还有一个重构的节点是,当你发现了代码中的一些槽糕设计、不合理的逻辑,或者是一些过时的代码时,也应该考虑重构。
如果因为手里有其他重要的事情,不能立马着手重构的话,也要加上一个 todo,或者备注一下。
当然,理想很丰满,现实很骨感。
实际工作中,每个人都知道重构很重要,但是却又有太多 “合理” 的理由不去重构。
比如:
目前的代码运行良好,轻易改动的话,会引入新的风险,而且需要重新测试、上线;我还有其他业务需求要完成,没有时间做重构;有重构的时间,学习一点新技术不好吗?
如果你有这样的想法,趁早纠正过来。
重构其实是一次对个人来说,很好的思考和实践的机会。
你会有一次深入的思考:如何设计代码更合理、更方便维护、更加适应需求变化。
然后会把思考的结果,用代码实现,并在这个过程中会去解决一些实际的问题。
因此,重构是你编程生涯中,很重要的成长机会,所以,千万不要错过。
天下难事必作于易,天下大事必作于细。千里之行,始于足下。
Just Do It.
四、重构有什么好处
我们在上一节其实也讲到了,重构对于我们程序员个人来说的一些好处。
但其实,重构对于整个项目来说,也有很大的收益。
因为,一个稍微大一点的项目里面,一定存在很多不合理的代码。
如果你不及时进行重构,那么在未来,可能会投入更多的时间来解决这些问题。
通常来说,重构有以下的一些好处:
- 可以将混乱、不正确或者重复的代码改造成干净、整洁的代码;
- 提高可读性,改善代码的可维护性以及整体结构和功能;
- 让代码更容易适应需求变更;
- 提升代码性能和执行效率。
五、哪些代码需要被重构
如果你在项目里发现如下这些代码,建议你立即重构。
- 重复代码❗
我们先来定义下“重复”的含义。
如果在你的项目里面有两个或更多地方表达的是相同的东西,并且如果变更了其中一个,就必须要变更其他几个。
像这样的代码,就属于重复代码。
我们来看一个例子:
void calculate(int money){
if (money >= 400) {
print('打折后的价格为¥:${money*0.7} RMB');
}else if(money >= 300){
print('打折后的价格为¥:${money*0.8} RMB');
}else if(money >= 200){
print('打折后的价格为¥:${money*0.9} RMB');
}else{
print('打折后的价格为¥:${money} RMB');
}
}
代码中反复出现了 价格为¥
这个字符串,假如现在需求变更了,需要把字符串改成 金额为¥
,那你就需要同时需求修改 4 处的内容。
这个例子就是典型的代码重复。
- 非正交设计❗
先来看看什么是正交。
“正交性”是几何学中的概念。若两条直线相交后构成直角,它们就是正交的。
“正交性”在计算科学中,表示 独立性或解耦性。
对于两个或多个事物,其中一个的改变不影响其他任何一个,则这些事物是正交的。
举个例子,在项目中,假如你改动了 UI 相关的代码,同时又不影响其他业务逻辑(比如数据库操作,网络访问逻辑等等),那么这样的系统,就属于设计良好的系统。
相反,如果你发现自己改动其中一处的代码,会影响很多地方,那么你就得思考一下,是否需要重构代码了。
- 过时的代码❗
比如一些古老久远的实现方式,废弃的代码,无用的注释,这些都算过时的代码,需要重构。
- 影响性能的代码❗
如果你发现某一处的代码实现存在性能问题,那就应该重构。
或者,你学习到了一些新的能提升性能的知识,那也应该重构。
六、重构时需要注意什么
1.尽量避免业务需求开发和重构同时进行,除非能保证新开发的功能和重构的代码之间没有任何关联。
2.确保有完整的测试流程,无论是单元测试还是 QA 同学参与的测试。
3.小步骤进行,并且每个小步骤后都进行测试,测试通过再进行下一步。
一个小步骤可以小到什么程度呢?
比如:将字段从一个类移动到另一个类,或者拆分方法,或者重命名变量,这些都算一个小步骤。
七、写在最后
尽早重构,经常重构。