简介
"将查询与修改操作分离"是提升代码纯净度的关键重构手法。通过将数据查询与状态修改操作解耦,可以消除副作用,提高代码的可测试性和可维护性。
针对的症状(代码坏味道)
- 方法同时返回结果和修改状态
- 存在具有副作用的查询方法
- 需要重复执行查询操作
- 测试时难以隔离状态变更
将查询与修改操作分离的详细步骤
- 识别混合方法
- 查找同时包含查询和修改的方法
- 标记副作用代码块
- 创建纯查询方法
- 复制原方法逻辑但不执行修改
- 确保无状态变更
- 创建修改方法
- 将副作用逻辑提取为新方法
- 返回void或操作结果
- 替换原方法
- 用查询方法+修改方法组合替换
- 调整客户端调用逻辑
示例
重构前代码:
class Account {
double withdraw(double amount) {
if (balance < amount) throw new IllegalArgumentException();
balance -= amount;
return balance;
}
}
重构步骤:
-
分离查询方法:
double getBalanceAfterWithdraw(double amount) { if (balance < amount) throw new IllegalArgumentException(); return balance - amount; } -
最终重构结果:
class Account { void withdraw(double amount) { balance = getBalanceAfterWithdraw(amount); } double getBalanceAfterWithdraw(double amount) { if (balance < amount) throw new IllegalArgumentException(); return balance - amount; } }
练习
基础练习题
-
简单操作分离
// 重构前 class Cart { int addItem(Item item) { items.add(item); return items.size(); } }
进阶练习题
-
复合操作分离
// 重构前 class Logger { String log(String message) { writeToFile(message); return getLastEntry(); } }
综合拓展练习题
-
状态缓存处理
// 重构前 class Cache { Object get(String key) { if (!data.containsKey(key)) { loadFromDB(key); } return data.get(key); } }
代码审查要点
-
优点:
- 消除方法副作用
- 提高代码可测试性
- 支持并发安全访问
-
潜在问题:
- 保持原子操作完整性
- 注意性能影响
- 处理异常传播方式