Split Variable 是什么
同一个变量被赋予含义不同的值时,拆成多个各自命名的变量:变量名准确、作用范围缩小、副作用减少。被反复重赋值的临时变量是重灾区——它先表示「临时结果」,后又表示「最终结果」,读者必须逐行追踪才能知道当前这个值代表什么。拆开之后,每个变量只承担一个含义。
基本信息
| 信号 | 变量被重新赋值且含义改变,需要写注释说明 |
|---|---|
| 做法 | 每个含义一个变量,能声明为不可变就声明 |
| 配套 | 循环中的累计变量可拆分或提炼为函数 |
| 收益 | 缩小可变范围,减少因误用导致的缺陷 |
常见形态
- 一个 result 变量先后存放中间结果与最终结果
- 循环里用同一个变量既当索引又当累计值
- 输入参数被就地改写后再当作输出使用
- 布尔变量在函数中途被改含义(先表示「已找到」,后表示「失败」)
- 同一个变量在不同分支里承担不同语义,靠上下文区分
拆分示例
拆分示例
// 之前:temp 先放周长,再放面积
void report(double height, double width) {
double temp = 2 * (height + width);
System.out.println("perimeter: " + temp);
temp = height * width; // 含义完全变了
System.out.println("area: " + temp);
}
// 之后:一个含义一个名字,而且都不可变
void report(double height, double width) {
final double perimeter = 2 * (height + width);
final double area = height * width;
System.out.println("perimeter: " + perimeter);
System.out.println("area: " + area);
}变量角色与拆分方式
| 角色 | 常见问题 | 处理 |
|---|---|---|
| 临时结果 | 一词多义,含义漂移 | 按含义拆名,改成不可变 |
| 累计值 | 与索引混淆 | 单独命名,或提炼为函数 |
| 收集器 | 重置时机不清 | 在循环内声明,避免跨轮复用 |
| 输出参数 | 被就地改写 | 改为返回值,调用方接收 |
能声明为不可变(final、const)就声明:编译期就挡住二次赋值,比靠评审提醒有效得多。做不到不可变时,至少让每个变量只在一个地方被赋值。
循环里的收集变量最容易拆错:如果把它提到循环外,多轮之间会相互污染;如果在循环内声明,每轮都是新实例,语义更清楚但要注意别在循环外引用。