Skip to content

Latest commit

 

History

History
226 lines (125 loc) · 7.07 KB

第10章 简化函数调用.md

File metadata and controls

226 lines (125 loc) · 7.07 KB

第十章 简化函数调用

10.1 修改函数名

做法

  • 检查函数签名是否被超类或子类实现过。如果是,需要针对每份实现分别进行如下步骤:
  • 声明一个新函数,将它命名为你想要的新名称,将旧函数的代码复制到新函数中,并进行适当调整。
  • 编译。
  • 修改旧函数,令他将调用转发给新函数。
  • 编译测试。
  • 找出旧函数的所有被引用点,修改他们,令他们改用新函数。每次修改后编译并测试。
  • 删除旧函数。
  • 编译测试。

10.2 Add Parameter (添加参数)

做法

  • 添加参数与重命名函数做法相似。

10.3 Remove Parameter(移除函数)

做法

  • 做法与10.2,10.1 类似

10.4 Separate Query from Modifier(将查询函数与修改函数分离)

动机

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

做法

  • 新建一个查询函数,令他返回值与原函数相同。

  • 修改原函数,令他调用查询函数,并返回获得的结果。

  • 编译测试。

  • 将调用原函数的代码改为调用查询函数,然后在调用查询函数的那一行之前,加上对原函数的调用,每次修改后,编译并测试。

  • 将原函数的返回值改为void,并删除其中所有的return语句。

10.5 Parameterize Method(令函数携带参数)

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

动机

做法

  • 新建一个带有参数的函数,使他可以替换先前所有的重复性函数。
  • 编译。
  • 将调用旧函数的代码改为调用新函数。
  • 编译,测试。
  • 对所有旧函数重复上述步骤,每次替换后,修改并测试。

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

针对该参数的每一个可能值,建立一个独立函数

做法

  • 针对参数的每一种可能值,新建一个明确函数。
  • 修改条件表达式的每一分支,使其调用合适的新函数。
  • 修改每个分支后,编译并测试。
  • 修改原函数的每一个调用点,改而调用上述的某个合适的新函数。
  • 编译,测试。
  • 所有调用端都修改完毕后,删除原函数。

10.7 Preserve Whole Object(保持对象的完整性)

改为传递整个对象

做法

  • 对你的目标函数新添一个参数项,用以代表源数据所在的完整对象。
  • 编译测试。
  • 判断哪些参数可以被包含在新添的完整对象中。
  • 选择上述参数之一,将被调用函数中原来引用该参数的地方,改为调用新添参数对象的相应取值函数。
  • 删除该参数。
  • 编译。测试。
  • 针对所有可从完整对象中获得的参数,重复上述过程。
  • 删除调用端中哪些带有被删除参数的代码。
  • 编译测试。

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

让参数接受者去除该项参数,并直接调用前一个函数

做法

  • 如果有必要,将参数的计算过程提炼到一个独立函数中。
  • 将函数本体内引用该参数的地方改为调用新建的函数。
  • 每次替换后,修改并测试。
  • 全部替换完后,使用Remove Parameter(277)将该参数去除。

10.9 Introduce Parameter Object引入参数对象

做法

  • 新建一个类,用以表现你想替换的一组参数。将这个类设为不可变。
  • 编译。
  • 针对使用该组参数的所有函数,实施Add Parameter(275),传入上述新建类的实例对象,并将此参数设为null。
  • 对于Data Clumps的每一项(在此均为参数),从函数签名中移除之,并修改调用端和函数本体。令他们都改而通过新的参数对象取得该值。
  • 每去除一个参数,编译并测试。
  • 将原先的参数全部去除之后,观察有无适当函数可以运用Move Method(142)搬移到参数对象中。

10.10 Remove Setting Method(移除设值函数)

去除该字段的所有设值函数

做法

  • 检查设值函数被使用的情况,看她是否只被构造函数调用,或者被构造函数所调用的另一个函数调用。
  • 修改构造函数,使其直接访问设值函数所针对的那个变量。
  • 编译测试。
  • 移除设置函数,将它所针对的字段设为final,
  • 编译测试。

10.11 Hide Method(隐藏函数)

将这个函数修改为private

做法

  • 经常检查有没有可能降低某个函数的可见度。

    使用lint一类的工具,尽可能频繁检查。当你在另一个类中移除对某个函数的调用时,也应该进行检查。

    特别对设值函数进行上述检查。

  • 尽可能降低所有函数的可见度。

  • 每完成一组函数的隐藏后,编译并测试。

10.12 Replace Constructor With Factory Method(以工厂函数替换构造函数)

做法

  • 新建一个工厂函数,让它调用现有的构造函数。
  • 将调用构造函数的代码改为工厂函数。
  • 每次替换后编译测试。
  • 将构造函数声明为private。
  • 编译。

10.13 Encapsulate Downcast(封装向下转型)

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

做法

  • 找出必须对函数调用结果进行向下转型的地方。

    这种地方通常出现在返回一个集合或迭代器的函数中。

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

    针对返回集合的函数,使用Encapsulate Collection(208)

10.14 Replace Error Code With Exception(以异常取代出错误码)

改用异常

做法

  • 决定应该抛出受控(checked)异常还是非受控(unchecked)异常;

    如果调用者有责任在调用前检查必要状态,就抛出非受控异常,

    如果想抛出受控异常,你就可以新建一个异常类,也可使用现有的异常类。

  • 如果找到该函数的所有调用者,对他们进行相应的调整,让他们使用异常。

    如果函数抛出非受控异常,那么就调整调用者,使其在调用函数前做适当检查,每次修改后,编译测试。

    如果函数抛出受控异常,那么就调整调用者,使其在try区段调用该函数。

  • 修改该函数的签名,令他反映出新用法。

  • 决定应该抛出受控异常还是非受控异常。

  • 新建一个函数,使用异常来表示错误状况,将旧函数代码复制到新函数,并做适当调整。

  • 修改旧函数的函数本体,让它调用上述新建函数。

  • 编译测试。

  • 逐一修改旧函数的调用者,令其调用新函数,每次修改后,编译并测试。

  • 移除旧函数。

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

修改调用者,使他在调用函数之前先做检查

做法

  • 在函数调用之前,放置一个测试语句,将函数内catch区段中的代码复制到测试句的适当if分支中。
  • 在catch区段起始处加入一个断言,确保catch区段绝对不会被执行。
  • 编译测试
  • 移除所有catch区段,然后将try区段内的代码赋值到try之外,然后移除try区段。
  • 编译测试。