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