0

0

Java中重构复杂if-else语句:使用卫语句和方法提取提升代码可读性

碧海醫心

碧海醫心

发布时间:2025-11-16 14:12:20

|

523人浏览过

|

来源于php中文网

原创

Java中重构复杂if-else语句:使用卫语句和方法提取提升代码可读性

java开发中,随着业务逻辑的增长和复杂化,我们常常会遇到深层嵌套的`if-else`语句,俗称“if-else地狱”。这种结构不仅使得代码难以阅读和理解,还增加了维护成本和引入bug的风险。尤其当条件判断依赖于多个动态输入时,代码的混乱程度会急剧上升。本文将介绍如何通过方法提取和卫语句(guard clauses)等重构技巧,将复杂的条件逻辑转化为清晰、模块化且易于管理的代码。

理解“if-else地狱”的问题

当业务规则涉及多个对象的状态检查和多层条件判断时,if-else语句很容易变得冗长且嵌套。例如,在处理商品定价逻辑时,可能需要检查订单详情、商品信息、用户来源、供应商策略等多个因素。原始代码示例如下:

if (orderDetail != null && item != null && !orderDetail.isUnitPriceModified()) {
  ItemSizeColorStyle itemSizeColorStyle = itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID());

  if (origin != null && (origin.contains("b2baccess") || (origin.contains(".myappdev") && !origin.contains("apps.myappdev")))) {
    RepGroupManufacturer repGroupManufacturer = repGroupManufacturerRepository.findByRepGroupIDAndManufacturerIDAndRecordDeleted(repGroupID, manufacturerID, NOT_DELETED);
    if (repGroupManufacturer != null && repGroupManufacturer.getB2bItemPricingPolicy() != null && repGroupManufacturer.getB2bItemPricingPolicy().equalsIgnoreCase(ReptimeConstants.SHOWRETAILPRICE)) {
      if (orderDetail.getItemSCSID() == null && item.getRetailPrice() != null) {
        orderDetail.setUnitPrice(item.getRetailPrice());
      } else {
        if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() != null) {
          orderDetail.setUnitPrice(itemSizeColorStyle.getRetailPrice());
        } else if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() == null && item.getRetailPrice() != null) {
          orderDetail.setUnitPrice(item.getRetailPrice());
        } else if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() == null && item.getRetailPrice() == null) {
          throw new NullPointerException("item price can not be null.");
        }
      }
    }
  }
}

这段代码存在以下问题:

  • 可读性差:多层嵌套导致代码难以一眼看清逻辑路径。
  • 维护困难:修改或添加新条件时,容易影响现有逻辑,且难以定位问题。
  • 高圈复杂度:增加了代码的测试难度和出错概率。

重构策略:方法提取与卫语句

为了解决上述问题,我们可以采用以下两种核心重构策略:

  1. 方法提取 (Method Extraction):将一个大型方法中处理特定职责的代码块抽取成独立的方法。这有助于提高代码的模块化程度,使每个方法只关注一个单一的职责。
  2. 卫语句 (Guard Clauses) / 早期返回 (Early Exit):在方法开头放置条件检查,如果条件不满足,则立即返回或抛出异常,避免进一步执行。这种方式可以有效减少嵌套层级,使主逻辑路径更加清晰。

示例代码重构

我们将上述复杂的定价逻辑重构为两个更小、更专注的方法:setUnitPrice 和 getUnitPrice。

立即学习Java免费学习笔记(深入)”;

1. setUnitPrice 方法:处理主要流程和前置条件

setUnitPrice 方法负责协调整个定价过程,并处理一些高级别的验证。它使用卫语句来快速排除不满足基本条件的场景,避免了深层嵌套。

public static void setUnitPrice(OrderDetail orderDetail, String origin) {
    // 卫语句:检查基本参数和订单状态
    if (orderDetail == null || item == null || orderDetail.isUnitPriceModified()) {
        return; // 不满足条件,直接返回
    }

    // 卫语句:检查来源条件
    // 注意:原始条件 `!origin.contains("b2baccess") || !origin.contains(".myappdev") && origin.contains("apps.myappdev")`
    // 逻辑可能需要根据实际业务调整,这里假设其意图是排除某些特定来源。
    // 如果原始意图是 `origin.contains("b2baccess") || (origin.contains(".myappdev") && !origin.contains("apps.myappdev"))`
    // 那么卫语句应该是 `!(origin.contains("b2baccess") || (origin.contains(".myappdev") && !origin.contains("apps.myappdev")))`
    // 为了简化和演示卫语句,我们假设一个简单的排除逻辑。
    if (origin == null || !(origin.contains("b2baccess") || (origin.contains(".myappdev") && !origin.contains("apps.myappdev")))) {
        return; 
    }

    // 查询RepGroupManufacturer
    RepGroupManufacturer repGroupManufacturer = repGroupManufacturerRepository
            .findByRepGroupIDAndManufacturerIDAndRecordDeleted(repGroupID, manufacturerID, NOT_DELETED);

    // 卫语句:检查制造商策略
    if (repGroupManufacturer == null ||
        repGroupManufacturer.getB2bItemPricingPolicy() == null ||
        !repGroupManufacturer.getB2bItemPricingPolicy().equalsIgnoreCase(ReptimeConstants.SHOWRETAILPRICE)) {
        return;
    }

    // 查询ItemSizeColorStyle
    ItemSizeColorStyle itemSizeColorStyle = itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID());

    // 调用辅助方法获取最终单价
    orderDetail.setUnitPrice(getUnitPrice(itemSizeColorStyle, item, orderDetail));
}

2. getUnitPrice 方法:专注于计算单价

getUnitPrice 方法的职责是根据 ItemSizeColorStyle 和 Item 信息来确定最终的单价。它也大量使用了卫语句来处理不同的定价逻辑分支。

Ideogram
Ideogram

Ideogram是一个全新的文本转图像AI绘画生成平台,擅长于生成带有文本的图像,如LOGO上的字母、数字等。

下载
public static Integer getUnitPrice(ItemSizeColorStyle itemSizeColorStyle, Item item, OrderDetail orderDetail) {
    // 卫语句:如果ItemSCSID为空且商品有零售价,则使用商品的零售价
    if (orderDetail.getItemSCSID() == null && item.getRetailPrice() != null) {
        return item.getRetailPrice();
    }

    // 卫语句:如果ItemSizeColorStyle有零售价,则使用其零售价
    if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() != null) {
        return itemSizeColorStyle.getRetailPrice();
    }

    // 卫语句:如果ItemSizeColorStyle无零售价但商品有零售价,则使用商品的零售价
    if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() == null && item.getRetailPrice() != null) {
        return item.getRetailPrice();
    }

    // 所有条件都不满足,且无法确定价格,抛出异常
    throw new NullPointerException("item price can not be null.");
}

注意:getUnitPrice 返回类型为 Integer 假设价格可以是 null 或一个整数。如果价格必须是非负整数,可以考虑返回 int 并使用 Optional 来表示可能缺失的价格,或者在调用处处理 null。

重构后的优势

通过方法提取和卫语句的运用,重构后的代码具有以下显著优势:

  • 提高可读性:每个方法都更短小精悍,职责明确,更容易理解其功能。setUnitPrice 方法展示了高层逻辑,而 getUnitPrice 则封装了具体的定价规则。
  • 降低复杂度:卫语句消除了深层嵌套,使代码路径扁平化,降低了圈复杂度。
  • 增强可维护性:当需要修改或添加新的定价规则时,只需修改 getUnitPrice 方法,而不会影响 setUnitPrice 中的其他逻辑。
  • 便于测试:每个小方法都可以独立进行单元测试,提高了测试的效率和覆盖率。
  • 代码复用:如果其他地方也需要获取商品单价,可以直接调用 getUnitPrice 方法。

其他重构思路(Map的应用场景)

虽然本例主要通过方法提取和卫语句来优化条件逻辑,但对于某些特定场景,Map 也可以用于重构if-else。Map 通常适用于根据一个明确的“键”来执行不同的“动作”或获取不同的“值”的场景,例如:

  • 策略模式:当有多种算法或行为需要根据某个条件动态选择时,可以将不同的策略实现放入 Map 中,通过键来获取并执行相应的策略。
  • 命令模式:将不同的命令对象存储在 Map 中,根据用户输入执行对应的命令。
  • 配置映射:将配置项(键)映射到对应的处理函数或值。

然而,对于本例中这种涉及复杂、顺序依赖的条件判断链,Map 并不总是最直接或最优雅的解决方案。本例的条件判断更像是决策树,而不是简单的键值映射。因此,方法提取和卫语句是更合适的选择。

总结

复杂的if-else结构是代码异味的一种常见表现。通过运用方法提取和卫语句等重构技术,我们可以有效地将混乱的条件逻辑转化为清晰、模块化且易于维护的代码。这不仅提升了代码的可读性和可测试性,也为项目的长期健康发展奠定了基础。在日常开发中,应当时刻警惕深层嵌套的if-else,并积极寻找机会对其进行优化。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

831

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

737

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

733

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16925

2023.08.03

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.4万人学习

C# 教程
C# 教程

共94课时 | 6.5万人学习

Java 教程
Java 教程

共578课时 | 45万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号