首页/开发/代码质量与评审速查/手法:Remove Assignments to Parameters(移除对参数的赋值)
重构手法62 条

手法:Remove Assignments to Parameters(移除对参数的赋值)

参数是调用方契约的一部分:在函数内改写参数会掩盖真实输入、制造调试困惑;改用局部变量承接中间值,保持参数只读。

别在函数里改写参数

参数是调用方与被调方之间的契约:在函数体内改写参数值,会让「输入到底是什么」这件事消失,阅读与调试都要在脑内重放一遍赋值过程。移除对参数的赋值,就是改用局部变量承接中间结果,让参数在整个函数里保持只读。

基本信息

为什么参数被改写后原始输入不可见,跟踪困难
做法局部变量承接中间值,参数视为只读
语言差异值传递语言影响小,引用语义语言容易牵连调用方对象
风格指南多数团队把禁止改写入参写成硬性检查项

典型使用场景

  • 累加与换算:用局部结果承接,而不是在入参上直接做加减
  • 默认值处理:用局部变量取默认值,保留「未传参」这一信息
  • 循环复用:局部变量做游标,函数语义更明确
  • 代码评审:把入参只读作为可执行的评审检查项
  • 静态检查:把禁止参数重赋值固化成规则,交给工具守住

Java 示例

Java 示例
// 之前:入参被就地修改,原始输入丢失
double discount(double inputVal) {
    if (inputVal > 100) inputVal -= 10;   // 原始值无法再观察
    return inputVal;
}

// 之后:局部变量承接,参数保持只读
double discount(double inputVal) {
    double result = inputVal;             // 中间结果独立存放
    if (result > 100) result -= 10;
    return result;
}

常见改写对照

场景不推荐推荐
累加直接对参数做加减局部变量承接后再返回
默认值给参数重新赋默认值局部变量赋值后再使用
对象字段改参数指向对象的字段返回新对象或使用局部变量
循环游标用参数当索引变量声明局部游标变量
值传递不等于安全:改写入参这个变量本身不影响调用方,但改写入参指向对象的字段会影响调用方。字符串、数组、集合、映射在多数语言里都是引用语义,这类副作用最隐蔽,评审要单独看对象字段赋值。
可变默认参数是同类问题的变体:用可变对象做默认值会被多次调用共享并累积,应改用表示缺失的占位值,在函数内部新建容器。

易错点

  • 在引用语义语言里忽略对象字段赋值:只改了局部变量,调用方数据仍被污染
  • 局部变量与原参数起名过近:读代码的人依然分不清谁是谁
  • 一味禁止改参数却放任全局变量:副作用换个地方藏,问题没有解决
  • 以为值传递语言就一定安全:容器与字符串仍是引用语义,照样能伤到调用方

数据来源与参考

  • 《重构》第 2 版 · 第 9 章(Remove Assignments to Parameters)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌