简单易懂读《重构》 - Duplicated Code(重复代码)

重复代码

  • 含义:
    干同一件事的代码在项目中的同一个类/兄弟类/毫不相关的类,重复出现。
  • 坏处:
    可读性差,重复劳动,可能造成性能降低等
  • 目标:
    设法合到一块,使其可以复用。
  • 实现方法:
    • 针对同一个类中两个函数含有相同表达式:
      Extract Method(提炼函数)
    • 针对两个兄弟子类含相同表达式:
      • 对两个类都使用Extract Method(提炼函数),然后再使用Pull Up Method(函数上移)
      • 如果函数只是类似,并不完全相同,可以将相似部分和差异部分割开,构成单独一个函数,运用Form Template Method (塑造模板函数)
      • 如果有些函数以不同的算法做相同的事,可以选其中一个比较清晰的,使用 Substitude Algorithm(替换算法) 将其他函数的算法替换掉。
    • 针对两个毫不相关的类:
      可以考虑对其中一个使用Extract Class (提炼类), 将重复代码提炼到独立类中,然后在另一个类内使用这个新类。也许还会有更复杂的情况,最终目的是使新类可以公用,并不会出现在其他地方。

本文涉及的重构方法

Extract Method (提炼函数)

  • 作用:
    消除做同样事代码,并使其功能可以复用。
  • 步骤:
  1. 创造一个新方法,从这个方法"做什么"来命名,而不是"怎样做"。
  2. 复制原方法代码,并处理方法内的变量,使其可以保证新方法的通用性。变量的处理可能会涉及到下面几个方法:
    • Split Temporary Variable (分解临时变量)
    • Replace Temp with Query (以查询取代临时变量)
  3. 替换原代码中使用此方法的地方为新的方法。
  4. 编译并测试
  • 重构思路:
    把代码中实现相同功能的部分抽取出来,提炼为一个可以共用的方法,然后把源代码的该部分替换为这个共用方法,如果涉及到参数传递的,需要做出对应修改。

建议:

  1. 根据项目情况合理设置方法的作用域
  2. 需要多个返回参数的时候,考虑使用Replace Temp with Query (以查询取代临时变量),或者 Replace Method with Method Object (以函数对象取代函数)

Pull Up Method (函数提升)

  • 作用:
    使用继承来消除多个子类的同样功能代码,使其方法可以复用。
  • 步骤:
  1. 检查这些函数是否做的事是一样的,如果看上去一样,实际不完全一致,可使用 Substitute Algorithm (替换算法)
  2. 如果方法名不同,考虑一下在提升以后的父类中统一方法名
  3. 如果该函数有用到子类的其他字段,考虑参考2个方法:
    • Pull Up Field (字段上移)
    • Self Encapsulate Field (自封装字段)
  4. 移除原来的函数,多测试。
  • 重构思路:
    通过继承来消除多个类中做相同事的代码,Pull Up的意思就是把一个class里的method提升到一个superclass中。

Form Template Method (塑造模板函数)

  • 作用:
    消除那些操作大致相同,具体实现不同的方法,避免代码重复
  • 步骤:
  1. 在各个子类里分解那些函数,把实现一致的函数的命名统一,实现不一致的那部分函数命名区别开。
  2. 对于那些完全不同的函数,使用Rename Method (函数改名),使所有的这些不同的函数名完全相同
  3. 运用Pull Up Method(函数提升) ,把所有函数移到超类中,将超类里那些代表不同操作的函数定义为抽象函数
  4. 移除原来的函数,多测试。
  • 重构思路:
    通过继承,把多个子类相同方法统一命名,不同的方法也统一命名,相同方法移到父类中时,使用一个名字,不同方法移到父类中时,使用不同方法并声明为抽象函数。

建议:

  1. 参考设计模式中的模板模式

Substitude Algorithm (替换算法)

  • 作用:
    代码更清晰,精炼。
  • 步骤:
  1. 写好另一个算法,测试,如果可以完全替代原来的算法,则替换。
  • 重构思路:
    使用更清晰精炼的代码实现来重构原有的代码逻辑。比如java8中提供stream()方法处理数据会比原来的实现精炼很多

建议:

  1. 多使用类库来实现,可以精炼现有代码。
  2. 保持清晰度,不能过于舍弃代码可读性来追求精炼度。

Extract Class (提炼类)

  • 作用:
    每个类各司其职,代码结构更清晰
  • 步骤:
  1. 理清并分解类所负的责任
  2. 建立一个新类,把责任归类并分离出来,如果类名已经不能符合原本指责范围,则需要重命名。
  3. 通过函数方法来提供旧类获取新类的数据。
  4. 搬移各个字段,可以运用 Move Field(搬移字段)Move Method (搬移函数) 来把原来类中的方法和字段搬到新类里
  5. 如果这些类中有互相获取数据的方法,尽量考虑改为单向获取数据的方法。
  6. 合理设置这些类的作用域
  • 重构思路:
    使用更清晰精炼的代码实现来重构原有的代码逻辑。比如java8中提供stream()方法处理数据会比原来的实现精炼很多

建议:

  1. 如果存在多线程并发或者事物的问题,需要多考虑是否使用此方法及如何使用。

你可能感兴趣的:(Java)