Fuhui

代码重构


重构自己的代码是一件幸福的事,重构别人的代码确是一件不幸的事。尤其是被重构代码的人还没有离职的时候…

重构切记引入意外复杂度,同时要保证代码功能单一,没有冗余的、意义不明的代码存在。还要保证最简API原则。一个接口好坏,一定要明确区分:它不能再处理更多业务了,还是这些业务已经不能再被剥离了。

临时变量

这是重构的一个重要切入点。方法体内临时变量太多,尤其是一些词不表意的临时变量,理解维护是一件非常痛苦的事情。

是否可以将临时变量直接替换成方法调用,或者将临时变量规整到一个粒度更小的方法体中。

重复

代码重复,多处copy相同的代码,会让人迫不及待的想要重构。

项目中重复代码过多,会给维护、开发带来很大的不便。一个简单的逻辑修改,但却涉及修改好多处代码,还不能保证涉及的部分都修改了。这确实是一件头疼的事。

所以代码要做好封装:

  1. 封装的粒度要把握好。一方面便于测试需要,另一方面通过组合,还能满足其他需求。
  2. 封装要考虑参数如何传递。包括是否应该包含成员变量,参数的个数多少合适。
  3. 封装的方法应该如何归类。怎样可以将方法归到最合适的类。

多态

当遇到很多的switch或者if-elseif的时候,可以考虑是否能用多态来替换。

比如下面的方法:

switch type {
    case movie.TV:
    case movie.Release
}

需要特别提醒:movie包的常量作为判断条件,该方法就最好应该在movie包中。这样当需求变更时,便体现出最小修改原则。

我们提取一个movieType的抽象类,然后依次对每个类型实现相应的方法,通过声明类型为movieType的成员变量,实现不同类型的统一调用。

这里体现的是模块化的思想。将系统拆分成独立的模块,降低耦合度。这样做的好处:便于扩展。当新的类型添加时,对老的业务来说:零干扰。

但某些情况下,这样的拆分模式可能会有小缺陷。当类型是一个频繁被添加、修改的参数时,这样的模式就显得很冗余。这时可以使用属性拆分。将各个类型中的属性实现多态,也可以称做是一种策略转移。

使用类替换枚举类型

当一个类内含有多个常量枚举类型时,可以考虑将枚举类型的值封装成新的对象。这也是一个切入点。举个例子:

// original code
const(
    Month int = iota
    Year int
) 

//modified code
//将这些常量封装到另一个package中

访问成员变量

两个分歧:直接访问VS间接访问。两者均有好处,