Move Method 搬移函数
你的程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被后者调用。在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是将旧函数完全移除。
动机
“搬移函数”是重构理论的支柱。如果一个类有太多行为,或如果一个类与另一个类有太多合作而形成高度耦合,我就会搬移函数。通过这种手段,可以使系统中的类更简单,这些类最终也将更干净利落地实现系统交付的任务。
我常常会浏览类的所有函数,从中寻找这样的函数:使用另一个对象的次数比使用自己所驻对象的次数还多。一旦我移动了一些字段,就该做这样的检查。一旦发现有可能搬移的函数,我就会观察调用它的那一端、它调用的那一端,以及继承体系中它的任何一个重定义函数。然后,会根据“这个函数与哪个对象的交流比较多”,决定其移动路径。
这往往不是容易做出的决定。如果不能肯定是否应该移动一个函数,我就会继续观察其他函数。移动其他函数往往会让这项决定变得容易一些。有时候,即使你移动了其他函数,还是很难对眼下这个函数做出决定。其实这也没什么大不了的。如果真地很难做出决定,那么或许“移动这个函数与否”并不那么重要。所以,我会凭本能去做,反正以后总是可以修改的。
做法
- 检查源类中被源函数所使用的一切特性(包括字段和函数),考虑它们是否也该被搬移。
- 如果某个特性只被你打算搬移的那个函数用到,就应该将它一并搬移。如果另有其他函数使用了这个特性,你可以考虑将使用该特性的所有函数全都一并搬移。有时候,搬移一组函数比逐一搬移简单些.
- 检查源类的子类和超类,看看是否有该函数的其他声明。
- 如果出现其他声明,你或许无法进行搬移,除非目标类也同样表现出多态性。
- 在目标类中声明这个函数。
- 你可以为此函数选择一个新名称——对目标类更有意义的名称。
- 将源函数的代码复制到目标函数中。调整后者,使其能在新家中正常运行。
- 如果目标函数使用了源类中的特性,你得决定如何从目标函数引用源对象。如果目标类中没有相应的引用机制,就把源对象的引用当作参数,传给新建立的目标函数。
- 如果源函数包含异常处理,你得判断逻辑上应该由哪个类来处理这一异常。如果应该由源类来负责,就把异常处理留在原地。
- 编译目标类。
- 决定如何从源函数正确引用目标对象。
- 可能会有一个现成的字段或函数帮助你取得目标对象。如果没有,就看能否轻松建立一个这样的函数。如果还是不行,就得在源类中新建一个字段来保存目标对象。这可能是一个永久性修改,但你也可以让它是暂时的,因为后继的其他重构项目可能会把这个新建字段去掉。
- 修改源函数,使之成为一个纯委托函数。
- 编译,测试。
- 决定是否删除源函数,或将它当作一个委托函数保留下來。
- 如果你经常要在源对象中引用目标函数,那么将源函数作为委托函数保留下来会比较简单。
- 如果要移除源函数,请将源类中对源函数的所有调用,替换为对目标函数的调用。
- 你可以每修改一个引用点就编译并测试一次。也可以通过一次“查找/替换”改掉所有引用点,这通常简单一些。
- 编译,测试。