跳到主要内容

代码中的坏味道

· 4 分钟阅读

节选自《重构2》,我们应该在何时进行重构呢?可以在发现代码中出现了坏味道的地方开始。

神秘命名

命名通常出现在以下情况中:函数命名、变量命名、字段命名,为变量命名通常是一件很头疼的事,如果你想不出一个好名字,首先检查以下,是否背后可能潜藏着更深的设计问题;如果不是的话,尝试一下 codelf 这个命名工具吧。

重复代码

一旦有重复代码出现,阅读这些代码是就必须要加倍仔细,留意其间细微的差别;当需要修改逻辑时,则需要找到所有使用类似逻辑的地方。提炼函数是解决这个问题最行之有效的办法了,将相似的部分提炼到一起,当其中有一些简单的逻辑差异时,可以在函数上增加参数进行差异化。

过长函数

小函数具有更好的阐释力、更易于分享、更多的选择,函数越长则越难于理解。name 如何分解函数呢?可以遵循的一条原则:每当感觉需要以注释说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途命名。 条件表达式和循环常常也是提炼的信号。当出现庞大的 switch 语句时,每个分支都可以提炼为函数;至于循环,可以将循环和循环内的代码提炼到一个独立的函数中。

过长的参数列表

过长的参数列表容易使人迷惑,可以使用一下方法来解决:

  1. 如果可以向某个参数发起查询来获取另一个参数,可以使用以查询取代参数
  2. 如果参数中有很多数据来自对某一对象的查询,可以将这个对象直接传入
  3. 几项参数总是同时出现,将这些参数合并为一个对象
  4. 使用类,将相同参数变成类的字段

全局变量

全局变量在任何一个角落都可以被修改,并且没有任何机制可以探测到底是哪段代码做了修改。在通常情况下,使用局部变量会是一个较好的方案;如果需要用到几个地方共用的变量时,可以将变量封装到模块内,然后调用函数修改,从而可以控制对这个变量的访问。

可变数据

对数据的修改可能会导致出乎意料的结果和难以发现的 bug,在一处更新了数据,却没有意识到另一处期望着完全不同的数据。

  • 可以使用封装变量,确保数据在很少的几个函数中进行
  • 同一个变量被用在不同用途时可以进行拆分
  • 设计 api 时,可以将查询和修改分离,确保不会调用有副作用的代码

TODO...