重构手法——代码健壮性增强类|代码洁癖治理|分解条件

简介

"分解条件"(Decompose Conditional)是一种重构手法,当条件逻辑较为复杂时,将条件判断和对应的操作分别提取到独立的方法中,能使代码结构更清晰,提高代码的可读性和可维护性。复杂的条件逻辑会让代码变得难以理解和修改,通过分解条件,可以将复杂的逻辑拆分成多个简单的逻辑片段。

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

  • 复杂的条件语句:条件判断中包含多个逻辑运算符(如 &&||),导致条件表达式冗长复杂。
  • 条件语句内的逻辑复杂:ifelseelse if 分支内包含大量代码,使代码的意图不明确。

分解条件(Decompose Conditional)的详细步骤

  1. 识别复杂条件逻辑
    • 寻找长条件表达式:在代码中找到包含多个逻辑运算符的条件判断语句。
    • 确认分支逻辑复杂:检查 ifelseelse if 分支内的代码是否包含较多的逻辑操作。
  2. 提取条件判断
    • 创建独立方法:为每个条件判断创建一个独立的方法,方法名应能清晰描述该条件的含义。
    • 移动条件表达式:将条件表达式复制到新方法中,并返回布尔值。
  3. 提取分支逻辑
    • 创建独立方法:为每个 ifelseelse if 分支内的代码创建独立的方法,方法名应能清晰描述该分支的操作。
    • 移动分支代码:将分支内的代码复制到新方法中。
  4. 替换原始代码
    • 调用新方法:在原始的条件语句中,用调用新方法的语句替换条件表达式和分支代码。
  5. 测试
    • 编译代码:确保代码编译通过,没有任何语法错误。
    • 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
    • 手动测试:如果有必要,进行手动测试以验证功能的正确性。
  6. 代码审查
    • 同行评审:让同事或其他团队成员审查你的更改,确保代码质量和可维护性没有下降。
    • 文档更新:如果项目有维护文档的习惯,记得更新相关文档,说明分解条件的影响。

示例

假设有一个方法根据日期判断是否为夏季促销时间,并进行相应的价格计算。

原始代码

java 复制代码
import java.util.Calendar;

public class PriceCalculator {
    private double basePrice;

    public PriceCalculator(double basePrice) {
        this.basePrice = basePrice;
    }

    public double calculatePrice() {
        Calendar calendar = Calendar.getInstance();
        int month = calendar.get(Calendar.MONTH);
        if (month >= Calendar.JUNE && month <= Calendar.AUGUST) {
            return basePrice * 0.8; // 夏季促销,八折
        } else {
            return basePrice;
        }
    }
}

重构步骤

  1. 识别复杂条件逻辑:条件判断 month >= Calendar.JUNE && month <= Calendar.AUGUST 用于判断是否为夏季。
  2. 提取条件判断:
    • 创建独立方法:创建 isSummer 方法。
    • 移动条件表达式:将条件表达式复制到 isSummer 方法中。
  3. 提取分支逻辑:
    • 创建独立方法:分别创建 calculateSummerPricecalculateNormalPrice 方法。
    • 移动分支代码:将分支内的代码复制到相应的新方法中。
  4. 替换原始代码:
    • 调用新方法:在 calculatePrice 方法中调用新方法。

重构后代码

java 复制代码
import java.util.Calendar;

public class PriceCalculator {
    private double basePrice;

    public PriceCalculator(double basePrice) {
        this.basePrice = basePrice;
    }

    public double calculatePrice() {
        if (isSummer()) {
            return calculateSummerPrice();
        } else {
            return calculateNormalPrice();
        }
    }

    private boolean isSummer() {
        Calendar calendar = Calendar.getInstance();
        int month = calendar.get(Calendar.MONTH);
        return month >= Calendar.JUNE && month <= Calendar.AUGUST;
    }

    private double calculateSummerPrice() {
        return basePrice * 0.8;
    }

    private double calculateNormalPrice() {
        return basePrice;
    }
}

练习

基础练习题

  1. 简单条件分解

    • 给定以下 Java 代码,根据用户年龄判断是否可以购买酒精饮料。请分解条件逻辑。

      java 复制代码
        public class AlcoholPurchaseChecker {
            public boolean canPurchaseAlcohol(int age) {
                if (age >= 21) {
                    return true;
                } else {
                    return false;
                }
            }
        }
  2. 多分支条件分解

    • 下面的 Java 代码根据学生的考试成绩给出不同的评价。请分解条件逻辑。

      java 复制代码
        public class GradeEvaluator {
            public String evaluateGrade(int score) {
                if (score >= 90) {
                    return "Excellent";
                } else if (score >= 80) {
                    return "Good";
                } else if (score >= 70) {
                    return "Average";
                } else {
                    return "Needs Improvement";
                }
            }
        }

进阶练习题

  1. 复杂条件分解与参数传递

    • 在这段 Java 代码中,根据用户的会员等级、消费金额和购买时间判断是否可以享受折扣。请分解条件逻辑,并正确处理参数传递。

      java 复制代码
        import java.util.Calendar;
      
      public class DiscountChecker {
          public boolean canGetDiscount(String membershipLevel, double totalSpent, Calendar purchaseTime) {
              int month = purchaseTime.get(Calendar.MONTH);
              if ((membershipLevel.equals("premium") && totalSpent > 500) || (month >= Calendar.DECEMBER && month <= Calendar.FEBRUARY)) {
                  return true;
              } else {
                  return false;
              }
          }
      }
  2. 条件分解与返回值处理

    • 给定以下 Java 代码,根据订单状态和库存数量进行不同的处理。请分解条件逻辑,并确保返回值正确处理。

      java 复制代码
        public class OrderProcessor {
            public String processOrder(String orderStatus, int inventory) {
                if (orderStatus.equals("pending") && inventory > 0) {
                    return "Process order";
                } else if (orderStatus.equals("cancelled")) {
                    return "Cancel order";
                } else {
                    return "Hold order";
                }
            }
        }

综合拓展练习题

  1. 多模块条件分解与代码审查模拟
    • 考虑一个简单的 Java 游戏系统,有玩家类 Player,在玩家攻击怪物时,根据玩家的等级、武器类型和怪物的防御状态判断攻击是否有效。同时,根据玩家的体力值和技能冷却时间判断是否可以使用技能。请对这些条件逻辑进行 "分解条件" 重构。

    • 假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。

      java 复制代码
        public class Player {
            private int level;
            private String weaponType;
            private int stamina;
            private boolean skillOnCooldown;
      
            public Player(int level, String weaponType, int stamina, boolean skillOnCooldown) {
                this.level = level;
                this.weaponType = weaponType;
                this.stamina = stamina;
                this.skillOnCooldown = skillOnCooldown;
            }
      
            public boolean attackMonster(int monsterDefense) {
                if ((level >= 10 && weaponType.equals("sword")) || (monsterDefense < 20)) {
                    return true;
                } else {
                    return false;
                }
            }
      
            public boolean useSkill() {
                if (stamina > 50 && !skillOnCooldown) {
                    return true;
                } else {
                    return false;
                }
            }
        }
相关推荐
爱吃烤鸡翅的酸菜鱼1 小时前
Java【网络原理】(4)HTTP协议
java·网络·后端·网络协议·http
魔道不误砍柴功1 小时前
Spring Boot 依赖注入与Bean管理:JavaConfig如何取代XML?
xml·spring boot·后端
Asthenia04122 小时前
Nginx详解:从基础到微服务部署的全面指南
后端
常年游走在bug的边缘2 小时前
Spring Boot 集成 tess4j 实现图片识别文本
java·spring boot·后端·图片识别
NovakG_2 小时前
SpringCloud小白入门+项目搭建
后端·spring·spring cloud
努力的搬砖人.3 小时前
Spring Boot 实现定时任务的案例
spring boot·后端
Asthenia04123 小时前
不知道LVS是什么?那你的系统设计题怎么回答!
后端
pedestrian_h3 小时前
springboot+vue3+mysql+websocket实现的即时通讯软件
spring boot·后端·websocket
AskHarries3 小时前
使用Cloudflare加速网站的具体操作步骤
后端
Asthenia04123 小时前
深入剖析架构设计中的接入层:Nginx、LVS、F5详解与面试应对
后端