重构手法——函数行为重塑类 | 语意 | 用异常替换错误代码

89 阅读2分钟

简介

"用异常替换错误代码"是改进错误处理机制的重要重构手法。通过将程序错误以异常形式抛出,代替传统的错误代码返回方式,可以提升代码可读性和错误处理能力。

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

  • 方法通过返回特殊值(如-1、null)表示错误状态
  • 多层嵌套的错误代码检查
  • 全局错误代码常量污染代码空间

用异常替换错误代码的详细步骤

  1. 定义异常类型
    • 创建继承自Exception的自定义异常类
    • 封装错误代码对应的错误信息
  2. 替换错误返回点
    • 将return errorCode改为throw new Exception
    • 移除方法返回值中的错误代码定义
  3. 调整调用方
    • 添加try-catch块处理异常
    • 移除原有的错误代码检查逻辑
  4. 清理残留代码
    • 删除不再使用的错误代码常量
    • 简化方法返回类型

示例

重构前代码:

class FileProcessor {
    public static final int ERROR_FILE_NOT_FOUND = -1;
    public static final int ERROR_READ_PERMISSION = -2;

    int processFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return ERROR_FILE_NOT_FOUND;
        }
        if (!file.canRead()) {
            return ERROR_READ_PERMISSION;
        }

        // 正常处理逻辑
        return 0;
    }
}

重构步骤:

  1. 定义文件处理异常:

    class FileProcessException extends Exception {
        public FileProcessException(String message) {
            super(message);
        }
    }
    
  2. 改造处理方法:

    void processFile(String path) throws FileProcessException {
        File file = new File(path);
        if (!file.exists()) {
            throw new FileProcessException("File not found: " + path);
        }
        if (!file.canRead()) {
            throw new FileProcessException("Read permission denied: " + path);
        }
    
        // 正常处理逻辑
    }
    
  3. 调用方改造:

    try {
        new FileProcessor().processFile("data.txt");
    } catch (FileProcessException e) {
        System.err.println("Error: " + e.getMessage());
    }
    

练习

基础练习题

  1. 简单错误代码替换

    // 重构前
    class Calculator {
        public static final int DIVIDE_BY_ZERO = -999;
    
        double divide(int a, int b) {
            if (b == 0) {
                return DIVIDE_BY_ZERO;
            }
            return a / (double) b;
        }
    }
    

进阶练习题

  1. 复合错误处理改造

    // 重构前
    class DatabaseConnector {
        public static final int ERROR_CONNECTION = 1001;
        public static final int ERROR_TIMEOUT = 1002;
    
        int connect(String url) {
            if (!validateUrl(url)) {
                return ERROR_CONNECTION;
            }
            if (checkTimeout(url)) {
                return ERROR_TIMEOUT;
            }
            // 连接逻辑
            return 0;
        }
    }
    

综合拓展练习题

  1. 分层错误处理重构

    // 重构前
    class PaymentGateway {
        public static final int SUCCESS = 0;
        public static final int INVALID_CARD = 1;
        public static final int BALANCE_INSUFFICIENT = 2;
    
        int processPayment(Card card, double amount) {
            if (!card.isValid()) {
                return INVALID_CARD;
            }
            if (card.getBalance() < amount) {
                return BALANCE_INSUFFICIENT;
            }
            // 支付处理
            return SUCCESS;
        }
    }
    

代码审查要点

  1. 优点:

    • 明确分离正常流程和错误处理
    • 支持异常传播机制
    • 增强错误上下文信息携带能力
  2. 潜在问题:

    • 避免过度使用受检异常
    • 确保资源释放(使用try-with-resources)
    • 保持异常继承体系的合理性