重构手法——函数行为重塑类 | 语意 | 用函数调用替换内联代码

58 阅读2分钟

简介

"用函数调用替换内联代码"是提升代码复用性的基础重构手法。通过将重复出现的代码片段提取为独立函数,可以有效减少代码冗余,增强可维护性,并提升代码表达能力。

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

  • 相同代码片段重复出现3次以上
  • 包含复杂业务逻辑的内联代码
  • 需要注释说明的代码块
  • 难以理解的表达式组合

用函数调用替换内联代码的详细步骤

  1. 识别重复模式
    • 使用代码对比工具查找相似代码块
    • 标记具有相同语义的代码片段
  2. 创建目标函数
    • 选择具有业务含义的函数名称
    • 处理必要的参数和返回值
  3. 替换调用点
    • 用函数调用替换原始代码
    • 保持原有接口兼容性
  4. 验证重构
    • 确保行为一致性
    • 更新单元测试

示例

重构前代码:

class OrderProcessor {
    void processOrder(Order order) {
        // 计算折扣
        double discount = order.getAmount() > 1000 ?
                order.getAmount() * 0.1 : 0;

        // 应用会员折扣
        if (order.isVIP()) {
            discount += order.getAmount() * 0.05;
        }

        // 其他处理逻辑...
    }

    void generateReport(Order order) {
        // 计算折扣(重复逻辑)
        double discount = order.getAmount() > 1000 ?
                order.getAmount() * 0.1 : 0;

        if (order.isVIP()) {
            discount += order.getAmount() * 0.05;
        }

        // 生成报表逻辑...
    }
}

重构步骤:

  1. 提取折扣计算函数:

    private double calculateDiscount(Order order) {
        double discount = order.getAmount() > 1000 ?
                order.getAmount() * 0.1 : 0;
    
        if (order.isVIP()) {
            discount += order.getAmount() * 0.05;
        }
    
        return discount;
    }
    
  2. 替换原始代码:

    class OrderProcessor {
        void processOrder(Order order) {
            double discount = calculateDiscount(order);
            // 其他处理逻辑...
        }
    
        void generateReport(Order order) {
            double discount = calculateDiscount(order);
            // 生成报表逻辑...
        }
    }
    

练习

基础练习题

  1. 简单重复代码提取
// 重构前
class Circle {
    double area(double radius) {
        return 3.14159 * radius * radius;
    }

    double circumference(double radius) {
        return 2 * 3.14159 * radius;
    }
}

进阶练习题

  1. 带条件判断的代码提取

    // 重构前
    class StringValidator {
        boolean isValid(String s) {
            return s != null && !s.isEmpty() && s.length() <= 100;
        }
    
        String formatInput(String s) {
            if (s == null || s.isEmpty() || s.length() > 100) {
                return "Invalid";
            }
            return s.trim();
        }
    }
    

综合拓展练习题

  1. 多上下文重复逻辑

    // 重构前
    class InventoryService {
        void checkStock(Product p) {
            if (p.getStock() < 10 && p.isPopular()) {
                sendRestockAlert(p);
            }
        }
    
        void updatePrice(Product p) {
            if (p.getStock() < 10 && p.isPopular()) {
                applyPriceIncrease(p);
            }
        }
    }
    

代码审查要点

  1. 优点:

    • 降低代码重复率
    • 集中业务逻辑处理
    • 提升可测试性
  2. 潜在问题:

    • 避免创建无意义的小函数
    • 保持函数单一职责原则
    • 注意参数传递的正确性