重构手法——函数行为重塑类 | 语意 | 将查询与修改操作分离

42 阅读2分钟

简介

"将查询与修改操作分离"是提升代码纯净度的关键重构手法。通过将数据查询与状态修改操作解耦,可以消除副作用,提高代码的可测试性和可维护性。

针对的症状(代码坏味道)

  • 方法同时返回结果和修改状态
  • 存在具有副作用的查询方法
  • 需要重复执行查询操作
  • 测试时难以隔离状态变更

将查询与修改操作分离的详细步骤

  1. 识别混合方法
    • 查找同时包含查询和修改的方法
    • 标记副作用代码块
  2. 创建纯查询方法
    • 复制原方法逻辑但不执行修改
    • 确保无状态变更
  3. 创建修改方法
    • 将副作用逻辑提取为新方法
    • 返回void或操作结果
  4. 替换原方法
    • 用查询方法+修改方法组合替换
    • 调整客户端调用逻辑

示例

重构前代码:

class Account {
    double withdraw(double amount) {
        if (balance < amount) throw new IllegalArgumentException();
        balance -= amount;
        return balance;
    }
}

重构步骤:

  1. 分离查询方法:

    double getBalanceAfterWithdraw(double amount) {
        if (balance < amount) throw new IllegalArgumentException();
        return balance - amount;
    }
    
  2. 最终重构结果:

    class Account {
        void withdraw(double amount) {
            balance = getBalanceAfterWithdraw(amount);
        }
    
        double getBalanceAfterWithdraw(double amount) {
            if (balance < amount) throw new IllegalArgumentException();
            return balance - amount;
        }
    }
    

练习

基础练习题

  1. 简单操作分离

    // 重构前
    class Cart {
        int addItem(Item item) {
            items.add(item);
            return items.size();
        }
    }
    

进阶练习题

  1. 复合操作分离

    // 重构前
    class Logger {
        String log(String message) {
            writeToFile(message);
            return getLastEntry();
        }
    }
    

综合拓展练习题

  1. 状态缓存处理

    // 重构前
    class Cache {
        Object get(String key) {
            if (!data.containsKey(key)) {
                loadFromDB(key);
            }
            return data.get(key);
        }
    }
    

代码审查要点

  1. 优点:

    • 消除方法副作用
    • 提高代码可测试性
    • 支持并发安全访问
  2. 潜在问题:

    • 保持原子操作完整性
    • 注意性能影响
    • 处理异常传播方式