重构-改善既有的代码设计(六)

    xiaoxiao2023-03-28  12

    1. 简化函数调用

    1.1 Rename Method(函数改名)

    函数的名称未能揭示函数的用途,修改函数名。 动机 函数的名称不能反映它的用途。 做法 - 检查函数签名是否被超类或子类实现过。如果是,则需要针对每份实现分别进行下列步骤。 - 声明一个新函数,将它命名为你想要的新名称。将旧函数的代码复制到新函数中,并进行适当调整。 - 编译。 - 修改旧函数,令它将调用转发给新函数。 - 编译,测试。 - 找出旧函数的所有被引用点,修改它们,令它们改而引用新函数。每次修改后,编译并测试。 - 删除旧函数。 - 编译,测试。 范例:略。

    1.2 Add Parameter(添加参数)

    某个函数需要从调用端得到更多信息。为此函数添加一个对象参数,让该对象带进函数所需信息。 动机 你需要添加参数才能完成工作。 做法 - 检查函数签名是否被超类或子类实现过。如果是,则需要针对每份实现分别进行下列步骤。 - 声明一个新函数,名称与原函数同,只是加上新添参数。将旧函数的代码复制到新函数中。 - 编译。 - 修改旧函数,令它调用新函数。 - 编译,测试。 - 找出旧函数的所有被引用点,将它们全部修改为对新函数的引用。每次修改后,编译并测试。 - 删除旧函数。 - 编译,测试。 范例:略。

    1.3 Remove Parameter(移除参数)

    函数本体不再需要某个参数,将该参数去除。 动机 函数不再需要某个参数。 做法 - 检查函数签名是否被超类或子类实现过。如果是,则需要针对每份实现分别进行下列步骤。 - 声明一个新函数,名称与原函数同,只是去除不必要的参数。将旧函数的代码复制到新函数中。 - 编译。 - 修改旧函数,令它调用新函数。 - 编译,测试。 - 找出旧函数的所有被引用点,将它们全部修改为对新函数的引用。每次修改后,编译并测试。 - 删除旧函数。 - 编译,测试。 范例:略。

    1.4 Separate Query from Modifier(将查询函数和修改函数分离)

    某个函数既返回对象状态值,又修改对象状态。建立两个不同的函数,其中一个负责查询,另一个负责修改。 动机 某个函数既返回对象状态值,又修改对象状态。 做法 - 新建一个查询函数,令它返回的值与原函数相同。 - 修改原函数,令它调用查询函数,并返回获得的结果。 - 编译。 - 编译,测试。 - 将调用原函数的代码改为调用查询函数。然后,在调用查询函数的那一行之前,加上对原函数的调用。每次修改后,编译并测试。 - 将原函数的返回值改为void,并删掉其中的所有return语句。 范例:略。

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

    若干函数做了类似的工作,但在函数本体中却包含了不同的值。建立单一函数,以参数表达那些不同的值。 动机 若干函数大部分代码重复。 做法 - 新建一个带有参数的函数,使它可以替换先前所有的重复性函数。 - 编译。 - 将调用旧函数的代码改为调用新函数。 - 编译,测试。 - 多所有旧函数重复上述步骤,每次替换后,修改并测试。 范例:略。

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

    你有个函数,其中完全取决于参数值而采取不同行为。针对该参数的每一个可能值,建立一个独立函数。 动机 如果某个参数有多种可能的值,而函数内又以条件表达式检查这些参数值,并根据不同参数值作出不同的行为,这时你就应该使用本项重构。 做法 - 针对参数的每一种可能值,新建一个明确函数。 - 修改条件表达式的每一个分支,使其调用合适的新函数。 - 修改每个分支后,编译并测试。 - 修改原函数的每一个被调用点,该而调用上述的某个合适的新函数。 - 编译,测试。 - 所有调用端都修改完毕后,删除原函数。 范例:略。

    1.7 Preserve Whole Object(保持对象完整)

    你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。改为传递整个对象 动机 函数的若干项参数属于同一个对象。 做法 - 对你的目标函数新添加一个参数项,用以代表原数据所在的完整对象。 - 编译,测试。 - 判断哪些参数可被包含在新添的完整对象中。 - 选择上述参数之一,将被调用函数中原来引用该参数的地方,改为调用新添参数对象的相应取值函数。 - 删除该项参数。 - 编译,测试。 - 针对所有可从完整对象中获得的参数,重复上述过程。 - 删除调用端中那些带有被删除参数的代码。 - 编译,测试。 范例:略。

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

    对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数本身也能够调用前一个函数。让参数接受者去除该项参数,并直接调用前一个函数。 动机 如果函数可以通过其他途径获得参数值,那么它就不应该通过参数取得该值。 做法 - 如果有必要,将参数的计算过程提炼到一个独立的函数中。 - 将函数本体内引用该参数的地方改为调用新建的函数。 - 每次替换后,修改并测试。 - 全部替换完成后,使用Remove Parameter将该参数去掉。 范例:略。

    1.9 Introduce Parameter Object(引入参数对象)

    某些参数总是很自然地同时出现。以一个对象取代这些参数。 动机 你常会看到特定的一组参数总是一起被传递。这样的一组参数就是所谓的Data Clumps(数据泥团),我们可以运用一个对象包装所有这些数据,再以该对象取代它们。 做法 - 新建一个类,用以表现你想替换的一组参数。将这个类设为不可变的。 - 编译。 - 针对使用该组参数的所有函数,实施Add Parameter,传入上述新建类的实例对象,并将此参数设为null。 - 对于Data Clumps中的每一项,从函数签名中移除之,并修改调用端和函数本体,令它们都改而通过新的参数对象取得该值。 - 每去除一个参数,编译并测试。 - 将原先的参数全部去除之后,观察有无适当函数可以运用Move Method搬移到参数对象之中。 范例:略。

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

    类中的某个字段应该在对象创建时被设值,然后就不再改变。去掉该字段的所有设值函数。 动机 如果你不希望在对象创建之后此字段还有机会被改变,那就不要为它提供设值函数(同时将该字段设为final)。 做法 - 检查设值函数被使用情况,看它是否只被构造函数调用,或者被构造函数所调用的另一个函数调用。 - 修改构造函数,使其直接访问设值函数所针对的那个变量。 - 编译,测试。 - 移除这个设值函数,将它所针对的字段设为final。 - 编译,测试。 范例:略。

    1.11 Hide Method(隐藏函数)

    有一个函数,从来没有被其他任何类用到。将这个函数修改为private。 动机 检查函数是否有必要对外公开。 做法 - 经常检查有没有可能降低某个函数的可见度。 - 尽可能降低所有函数的可见度。 - 每完成一组函数的隐藏之后,编译并测试。 范例:略。

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

    你希望在创建对象时不仅仅是做简单的建构动作。将构造函数替换为工厂函数。 动机 检查函数是否有必要对外公开。 做法 - 新建一个工厂函数,让它调用现有的构造函数。 - 将调用构造函数的代码改为调用工厂函数。 - 每次替换后,编译并测试。 - 将构造函数声明为private。 - 编译。 范例:略。

    1.13 Encapsulate Downcast(封装向下转型)

    某个函数返回的对象,需要由函数调用者执行向下转型。将向下转型动作移到函数中。 动机 函数返回的对象需要向下转型。 做法 - 找出必须对函数调用结果进行向下转型的地方。 - 将向下转型动作搬移到该函数中。 范例:略。

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

    某个函数返回一个特定的代码,用以表示某种错误情况。改用异常。 动机 程序中某些函数返回一个错误码来代表程序运行有异常。 做法 - 决定应该抛出受控异常还是非受控异常。 - 找到该函数的所有调用者,对它们进行相应调整,让它们使用异常。 - 修改该函数的签名,令它反映出新用法。 范例:略。

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

    面对一个调用者可以预先检查的条件,你抛出了一个异常。修改调用者,使它在调用函数之前先做检查。 动机 在该用条件检查的地方使用了异常。异常只应该被用于异常的、罕见的行为,也就是那些产生意料之外的错误行为。 做法 - 在函数调用点之前,放置一个测试语句,将函数内catch区段中的代码复制到测试句的适当if分支中。 - 在catch区段起始处加入一个断言,确保catch区段绝对不会被执行。 - 编译,测试。 - 移除所有catch区段,然后将try区段内的代码复制到try之外,然后移除try区段。 - 编译,测试。 范例:略。 本文引用自图灵程序设计丛书:重构 改善改善既有的代码设计。

    转载请注明原文地址: https://ju.6miu.com/read-1210763.html
    最新回复(0)