首页/开发/代码质量与评审速查/手法:Preserve Whole Object(保持对象完整)
重构手法62 条

手法:Preserve Whole Object(保持对象完整)

从对象取出多个字段只为传参时,改为直接传对象:减少字段级耦合,被调函数可自行取用需要的数据;边界场景注意传递依赖范围是否变大。

是什么

保持对象完整(Preserve Whole Object)针对的是「从对象里取出若干字段只为传参」的写法:与其在调用处逐个取值再传进去,不如直接传递对象本身,由被调用方自行取用需要的数据。这样能减少字段级耦合——对象新增字段时不必修改调用链上的每一层。代价与收益需要一起评估:若被调用方因此引入了它本不该依赖的层次,传递对象反而扩大了耦合范围。

识别与做法

信号调用处把对象的多个字段拆开传入,例如按下界与上界分别传参
做法改为传递对象本身,被调方自行取值
收益减少字段级参数,新增字段时改动范围更小
权衡评估被调方是否因此与对象所在层次产生了新依赖

典型使用场景

  • 区间范围判断:把拆分出的上下界改为直接传区间对象
  • 订单处理:多处调用都在传客户编号、名称、等级,改为传客户对象
  • 统计计算:多个指标函数都从同一条记录取字段,改为接收记录本身
  • 配置传递:把零散配置项改为传递配置对象,新增项时不必改签名
  • 跨层调用:仅在被调方确实需要该对象语义时传对象,而非仅为了省参数

示例

示例
// 调整前:把区间拆成上下界传入
boolean withinPlan(Plan plan, double low, double high) {
    return plan.withinRange(low, high);
}

// 调整后:直接传区间对象,由被调方取值
boolean withinPlan(Plan plan, Range range) {
    return plan.withinRange(range);
}

传对象还是传字段

情形建议理由
调用处只是搬字段传对象减少字段级耦合与重复取值
被调方与对象不在同一层次传字段或定义精简契约避免引入跨层依赖
对象携带大量无关字段定义精简的契约对象防止被调方意外依赖无关数据
对象可变且被调方会写入传不可变副本或只读接口避免读参数变成写参数
该对象是外部系统模型经适配后传本地契约防止外部结构变化传导到内部
传递对象后要防止被调方顺手修改:读参数变成写参数是这类改造最常见的副作用。可以在类型层面提供只读视图,或在文档中明确该参数只读。
对象过大时先考虑拆分:如果被调方只需要其中三四个字段,而对象包含几十个字段,说明这个对象本身承担了过多职责,应先处理它的边界问题。

落地检查清单

  • 被调方确实需要该对象的多个字段或整体语义
  • 传递后没有跨层或跨模块的新依赖
  • 参数保持只读语义,内部状态不被意外修改
  • 对象过大时先评估是否需要拆分

易错点

  • 整对象传入后被随手改了字段:读参数变成写参数,调用方数据被意外修改
  • 为省参数引入跨层依赖:分层约束被打破,底层开始依赖上层模型
  • 把外部系统模型直接传进内部:外部结构变化直接传导到核心逻辑
  • 对超大对象也整体传递:被调方与对象的全部字段耦合,改动影响面反而扩大

数据来源与参考

  • 《重构》第 2 版 · 第 11 章(Preserve Whole Object)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌