07.重构-简化函数调用

1. 问题及方案

  • 函数名称不清晰:Rename Method;
  • 参数不明确:Add Parameter、Remove Parameter;
  • 参数过多:Preserve Whole Object、Introduce Parameter Object;
  • 函数参数来自该函数可以获取的对象:Replace Parameter with Method;
  • 参数被用于条件表达式:Replace Parameter with Explicit Method;
  • 多个相似函数添加参数:Parameterize Method;
  • 查询命令函数分离:Separate Query from Modifier;
  • 不必要的暴露:Hide Method、Remove Setting Method;
  • 隐藏创建对象:Replace Constructor with Factory Method;
  • 转型:Encapsulate Downcast;
  • 错误码、异常、测试:Replace Error Code with Exception、Replace Exception with Test;

2. Rename Method(函数改名)

修改函数名称,更加清晰明了。

3. Add Parameter(添加参数)

为函数添加参数,带进所需信息。

3.1 动机

请先确认是否一定需要添加新参数:

  • 你能从已有参数得到所需信息么?
  • 有可能通过某个函数得到所需信息么?
  • 这个函数是否应该属于拥有该信息的对象所有?
  • 现有参数过多,是否考虑使用 Introduce Parameter Object?
    ps:若旧函数是接口一部分,不好删除,请标记为 deprecated(不赞成)。

4. Remove Parameter(移除参数)

将不需要的参数移除。

5. Separate Query from Modifer(将查询函数和修改函数分离)

建立两个不同的函数,一个负责查询,另一个负责修改。

5.1 动机

  • 明确表示“有副作用”和“无副作用”两种函数之间的差异;
  • 任何有返回值的函数,都不应该有看得到(提取出查询函数,将结果缓存到某个字段)的副作用。
    ps:多线程环境下,建立第三个函数来做“查询-修改”,该还是调用独立的查询函数和修改函数,并被声明为 synchronized。若为声明为 synchronized,则将它们的可见范围限制在包级别或 private 级别。如此就能保证安全、同步的操作。

6. Parameterize Method(令函数携带参数)

建立单一函数,以参数表达那些不同的值。

6.1 动机

多个函数处理类似工作,仅因为值不同而略有不同。

7. Replace Parameter with Explicit Methods(以明确函数取代参数)

问题:函数完全取决于参数值而采取不同行为。
针对该参数的的每一个可能值,建立一个独立函数。
ps

  • 与 Parameterize Method 正好相反。
  • 若参数值对函数行为没太多影像,就不该使用该重构手法。
  • 若需要条件判断,考虑使用 Replace Conditional with Polymorphism。

8. Preserve Whole Object(保持对象完整)

将从某个对象取出某些值作为参数传递改为直接传递整个对象。
ps

  • 两面性,该重构手法会产生依赖关系,请考虑后在使用。
  • 先考虑 Move Method。

9. Replace Parameter with Methods(以函数取代参数)

问题:对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数本身也能调用前一个函数。
让参数接受者去除该项参数,直接调用前一个函数。

9.1 动机

如果函数可以通过其他途径获取参数,就不应该通过参数传递。应尽可能缩短参数列的长度。

10. Introduce Parameter Object(引入参数对象)

以一个对象取代这些参数。

10.1 动机

特定的一组参数总是被一起传递,好几个函数都使用这组参数。这就是所谓的 Data Clumps(数据泥团)。

11. Remove Setting Method(移除设值函数)

若某个字段在对象创建后就不再改变,则应移除该字段的所有设值函数。

12. Hide Method(隐藏函数)

该函数不被外界使用,请设为 private。

13. Replace Constructor with Factory Method(以工厂函数取代构造函数)

将构造函数替换为工厂函数。

13.1 动机

  • 在派生类中以工程函数取代类型码;
  • 以明确函数创建子类;

14. Encapsulate Downcast(封装向下转型)

将向下转型动作移到函数中。

15. Replace Error Code with Exception(以异常取代错误码)

某个函数返回一个特定的代码,用以表示某种错误情况。改用异常。

16. Replace Exception with Test(以测试取代异常)

问题:面对一个调用者可以预先检查的条件,你抛出了一个异常。
修改调用者,使它在调用函数之前先做检查。

16.1 动机

  • 异常滥用情况,异常只应该被用于意料之外的错误行为,而不应该成为条件检查的替代品。
    ps:我自己的坏习惯就是滥用异常,而且统一捕获。

参考

  • 《重构-改善既有代码的设计》(第10章)
坚持原创技术分享,您的支持将鼓励我继续创作!