我们常把祖传代码称为“屎山”。殊不知,在我们带着一脸鄙夷的神情拼命远离祖传代码的同时,我们自己也在不断制造着各种垃圾代码。有一天,当我们离开时,别人又在一边翻看着我们留下的垃圾,一边在心里不停骂娘。
想要摆脱互相坑的恶性循环,提高代码质量势在必行。重构,正是提高代码质量最有力的方式之一。那么什么是重构呢?用学术一点的语言说,重构是指不改变软件可观察行为的前提下,对软件内部设计的改进和优化。简单来说,就是保持功能不变,对代码的结构和可读性进行改善。
下面我们举一个经典的栗子,来感受一下shit是怎么产生的,以及我们怎么通过重构来“变废为宝”。假设我们要开发一个程序,实现“把大象放进冰箱里”。
场景1:无意义的命名
function 把大象放冰箱里(){
a();
b();
c();
}
看了上面的代码,你能明白程序都做了什么吗?如果真这么写程序,恐怕没人能读懂吧。但是很多时候,我们还是把命名规范统统抛到脑后,活生生把高级语言写成了机器语言。起个好名字对于写好程序很关键,非常关键。不合理的命名不仅难以阅读,有时候甚至会将人引入误区。
TIP 1:多花点时间,起个好名字。
什么样算是好名字呢?表达含义清晰准确,方法尽量使用动词,变量尽量使用名词。现代IDE的提示功能都很强大,因此不要害怕名字过长。另外,如果遇到现有代码里不合理的名字,顺手改了吧。
场景2: 代码过长,逻辑结构不清晰
function 把大象放冰箱里(){
把手放在冰箱把手上();
手握住冰箱把手();
手用力拉冰箱把手();
把冰箱门拉到180度角();
把冰箱里杂物清理干净();
去叫20个汉子();
20个汉子一起把大象抬起来();
把大象往冰箱里塞();
把手放在冰箱把手上();
手握住冰箱把手();
手用力拉冰箱把手();
把冰箱门拉到0度角();
}
上面的代码可以说又长又乱,那么问题出现在哪呢?代码是有不同抽象层级的,把不同层级的代码放到一起,就很容易引起混乱。同时,不同抽象层级代码混到一起,也是一个方法中代码过长的主要原因。解决的方法也很简单,根据代码的逻辑,把相同抽象层级的代码提取到一个独立方法中。
TIP 2:保证方法(函数)中只存在同一个抽象层级的代码。
TIP 3:保持方法(函数)短小。
比如上面代码中前四行其实就是在说“把冰箱门打开”这件事情,中间四行是在说“把大象放进冰箱”这件事情,后面四行是在说“把冰箱门关上”这件事情。因此,我们可以对这个方法进行如下重构:
function 把大象放冰箱里(){
把冰箱门打开();
把大象放进冰箱();
把冰箱门关上();
}
function 把冰箱门打开() {
把手放在冰箱把手上();
手握住冰箱把手();
手用力拉冰箱把手();
把冰箱门拉到180度角();
}
function 把大象放进冰箱() {
把冰箱里杂物清理干净();
去叫20个汉子();
20个汉子一起把大象抬起来();
把大象往冰箱里塞();
}
function 把冰箱门关上(){
把手放在冰箱把手上();
手握住冰箱把手();
手用力拉冰箱把手();
把冰箱门拉到0度角();
}
看看这样是不是清晰多了?对于读代码的人,我们可以很清晰地了解到大象放冰箱里所需的3个步骤。如果需要关注其中每个步骤究竟怎么实现的,再深入每个独立方法去查看细节就可以了。
场景3 错误/过期的注释
function 把大象放冰箱里(){
把冰箱门打开();
// 这个方法用于把狮子放进冰箱里
把大象放进冰箱();
把冰箱门关上();
}
注释是代码的重要组成部分。然而,在代码修修补补的过程中,我们总是忘记维护注释,导致注释和代码不匹配。正如上面的例子中,程序原来可能是用来把狮子放进冰箱的,但是后来需要发生变更,把狮子换成了大象,而注释却没有进行修改。
TIP 4 时刻保持注释和代码匹配。
总结
前人栽树,后人乘凉。前人栽shit,后人:???为了防止世界被破坏,为了守护世界的和平,改善代码质量,从重构做起。
相关书籍推荐
本文中提到的重构技巧只是一小部分,如果你对代码有洁癖,如果你想成为一个clean coder,可以去阅读以下两本书:
- 《代码整洁之道》
- 《重构:改善既有代码的设计》
网友评论