首页/开发/代码质量与评审速查/手法:Introduce Parameter Object(引入参数对象)
重构手法62 条

手法:Introduce Parameter Object(引入参数对象)

把总是成组出现的参数替换为一个对象:调用更短、默认值与校验有归属,后续行为也能逐步搬进该对象;适用于 Data Clumps 坏味道。

参数对象是什么

把总是成组出现的参数替换为一个对象:调用更短,默认值与校验有了归属,后续行为也能逐步搬进该对象。它针对的是数据泥团这类坏味道——同一组参数在多个函数签名里反复出现,任何一个新字段都要改所有签名。

基本信息

信号同一组参数在多个函数中重复出现
收益参数传错更少见,可承载校验与行为
延伸手法保持对象完整:整体传入,而不是拆成字段
不该用的场景只在单个函数内使用,就不值得建类
配套手法提取类、以对象替换基本类型

典型使用场景

  • 时间区间以两个参数反复传递
  • 地址被拆成多参数一路透传到存储层
  • 分页参数(页码、条数、排序)在每个查询方法重复
  • 搜索条件成组出现,调用方还常传错顺序
  • 需要给调用链补新字段时,避免改动所有签名

引入前后

引入前后
// 之前:三个参数成组出现,新增字段要改所有签名
schedules.add(from, to, name);

// 之后:成组参数合并为对象,校验有归属
schedules.add(new DateRange(from, to), name);

// DateRange 内部负责:先后顺序校验、区间是否包含某天、长度计算

引入前后的关注点

关注点引入前引入后
参数个数多且成组出现缩短,调用意图更清楚
校验位置散落在各调用方集中在新对象构造处
新增字段要改所有签名只需改对象与相关调用
不要只在单个函数用到时急着建类:等重复模式出现(两处以上,或明显会扩散)再抽象,否则只是多了一层包装。
参数对象字段全公开等于没封装:校验仍散落在外面,新对象沦为数据袋。把约束放进构造或校验方法,再考虑让它承载行为。
参数对象与整体传入要分清:前者是从多个参数里归纳出的新概念,会引入新类型;后者是把已有对象整体传入,只是减少拆字段传递的动作。

易错点

  • 参数对象字段全公开:校验仍散落在外,问题只是换了写法
  • 只在单个函数内使用就建类:抽象收益不足,包装成本先付
  • 建了对象却仍逐个拆字段传递:调用链没变短,还多了一层转换
  • 把不相关的参数凑进同一对象:字段之间没有内聚,调用方要传无意义的值

数据来源与参考

  • 《重构》第 2 版 · 第 6 章(Introduce Parameter Object)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌