首页/开发/代码质量与评审速查/手法:Move Function(搬移函数)
重构手法62 条

手法:Move Function(搬移函数)

把函数搬到更合适的位置:引用某个模块更多的函数应住在那个模块里;搬移前先看调用方分布与依赖方向,避免制造反向依赖。

Move Function 是什么

把函数搬到更合适的位置:引用某个模块更多、依赖那个模块数据更多的函数,理应住在那个模块里。搬移前先看调用方分布与依赖方向,避免为了消除一处别扭而制造反向依赖。这类搬移是划分模块边界最基础的动作,往往和 Move Field 一起做。

基本信息

判断函数与哪个模块的耦合更深(引用次数与数据依赖)
步骤确认依赖方向 → 搬移 → 更新引用 → 删除旧位置
配套Move Field、Extract Function、引入中间委托
风险跨发布边界搬移会改变可见性

判断线索

  • 函数频繁访问另一个类的字段,说明它待错了地方
  • 函数签名里总有同一个对象参数,等于隐性依赖
  • 函数名与所在模块的主题不符,读代码时要来回跳
  • 搬移后能让某个类从「数据容器」变成有行为的对象
  • 调用方集中在另一个模块,留在原处只会让每次调用都要跨层

方向示意

方向示意
// 之前:Account 上计算透支费用,实则规则依赖 AccountType
class Account {
    double overdraftCharge(int daysOverdrawn) {
        if (isPremium()) return daysOverdrawn * 1.75;
        return isPremium() ? daysOverdrawn * 1.75
             : 10 + daysOverdrawn * 0.85;
    }
}

// 之后:规则归 AccountType,Account 只做委托
double overdraftCharge(int daysOverdrawn) {
    return type.overdraftCharge(daysOverdrawn);
}

搬移决策

观察移动方向注意
函数大量访问 B 的字段移到 B先确认 B 不是基础设施细节
函数在 A 与 B 都被调用留在公共上游避免两侧各自复制一份
函数与类同名前缀不符按职责重命名或搬移先改名再搬,改动更好审
搬移会引入反向依赖改用依赖倒置在内层定义接口,外层实现
搬移函数比搬移字段容易,因为它不影响数据结构。遇到字段不好搬时,可以先把函数搬过去、让原类保留一个转发方法,等调用方都迁移完再删掉转发。
跨发布边界的搬移要格外小心:被搬到内部包的公开方法,下游可能已经依赖;搬移的同时要考虑可见性与兼容期,必要时保留一个标注废弃的转发入口。

易错点

  • 只搬函数不搬它依赖的字段:依赖关系反而绕远,每次调用多一次跳转
  • 跨模块搬移忽略发布边界:内部工具方法被下游误用,之后不敢再改
  • 搬移与改名一起做:PR 过大,评审者分不清哪些是位移哪些是语义变化
  • 搬移后旧方法未删:两份实现并存,修改时只改一处

数据来源与参考

  • 《重构》第 2 版 · 第 8 章(Move Function)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌