Talk about IF-ELSE practice optimization in business code


Foreword: When you are working with simple and repetitive business code, you need to keep thinking and summarizing the methodology, so that you can grow

IF-ELSE branch judgment is an inevitable program statement in writing business code, which can help us solve branch judgment, but when the business in a method is slightly complicated, there will be many IF-ELSE branches, and various nested judgments may occur And process processing.

Insert picture description here
This article does not involve best practices, just talk about the summary of my daily work. There are six points in total. These six points are not progressive optimization. There is no better or worse. The important thing is to apply to a specific business code process. Choose Appropriate and simple methods are the most important.

1. It is best to avoid branch judgment

Since branch judgment is troublesome, it is best to avoid branch judgment. But this seems too ideal, but we can avoid branch judgment for some simple judgment logic. The avoidance mentioned here is not no branch judgment, but learn to use existing tools to avoid embedding branch judgment in our own business code, such as The following case compares the numerical value, so you can use the Math tool class of the JDK to handle it. Furthermore, some collection operations can also be handled by the collection toolkit.

【ordinary】

 double result;
  if (value <= MIN_LIMIT) {
    
    
      result = MIN_LIMIT;
  } else {
    
    
      result = value;
  }

【optimization】

double result = Math.max(MIN_LIMIT, value);
2. Minimize the scope of conditions

Minimize the scope of conditions, try to put forward common processing code, you can use common variables to process the same logic code
[ordinary]

  Result result = service.doWork();
  if (result.isSuccess()) {
    
    
      String message = "任务处理成功";
      smsService.sendMessage(user.getPhone(), message);
  } else {
    
    
      String message = "任务处理失败:" + result.getMessage();
      log.warn(message);
      smsService.sendMessage(user.getPhone(), message);
  }

【optimization】

 String message;
 Result result = service.doWork();
 if (result.isSuccess()) {
    
    
     message = "任务处理成功";
 } else {
    
    
     message = "任务处理失败:" + result.getMessage();
     log.warn(message);
 }
 smsService.sendMessage(user.getPhone(), message);
3. Conditional filter location

The location of conditional screening is not related to the scalability and readability of the code, but the optimization on IF-ELSE. If there are multiple conditional screening judgments, put the judgment branch that can filter out most of the data in the front, which will help improve the code processing efficiency.

Filter out special situations in advance and pay more attention to core business logic

4. Guardian sentences

Guardian statement is to split a complex conditional expression into multiple conditional expressions. For example, if multiple if-elseif-else are nested, they can be split into multiple ifs. Such as the following code

【ordinary】

 public void test () {
    
    
     if (isWeekend()) {
    
    
         if (isRest()) {
    
    
             System.out.println("看书学习");
         } else {
    
    
             System.out.println("加班");
         }
     } else {
    
    
         //这里省略了周一到周五的分支判断
     }
 }

[Optimization]
Description:
There are two points involved:
1. Replace multiple nested IF-ELSE by setting multiple IFs. By setting multiple IFs, the code will look easier to read, and for the processing logic in each IF You can also create a method separately through code extraction, such as the following code looks better

public Object test() {
    
    
    if (!isWeekend()) {
    
    
      return doSomething1();
    }
    if (isRest()) {
    
    
     return   doSomething2();
    }
    if (other()) {
    
    
     return   doSomething3();
    }
    return   doSomething4();
}

2. Through the method of guarding sentences, filter out in advance 特殊情况, so that you can focus more on the realization of core business codes.

public void test() {
    
    
    // 提前过滤掉`特殊情况`
    if (!isWeekend()) {
    
    
        System.out.println("XXX");
        return; // 提前return
    }
    //提前过滤掉`特殊情况`
    if (isRest()) {
    
    
        System.out.println("XXX");
        return; // 提前return
    }
    //更关注于 `核心业务`代码实现
     doSomething();
}
5. Select the branch, prefer to use the switch statement instead of the if-else statement

If-else statement, each if conditional statement must be added with calculations until the if conditional statement is true. The switch statement is optimized for jumps, and the tableswitch or lookupswitch instructions are used in Java to achieve higher efficiency for multi-constant selection branch processing. Experiments have shown that if each branch has the same probability of occurrence, if-else statements are more efficient when there are less than 5 branches, and switch statements are more efficient when there are more than 5 branches.
【ordinary】

if (i == 1) {
    
    
    ...; // 分支1
} else if (i == 2) {
    
    
    ...; // 分支2
} else if (i == ...) {
    
    
    ...; // 分支3
} else {
    
    
    ...; // 分支n
}

【optimization】

switch (i) {
    
    
    case 1 :
        ... // 分支1
        break;
    case 2 :
        ... // 分支2
        break;
    case ... :
        ... // 分支n
        break;
    default :
        ... // 分支n+1
        break;
}
6. The branch is modified into a ternary operator

For the branch with a single return value of the judgment result, it is relatively simple, so you can use the ternary operator to replace the corresponding branch. For example, compare numerical values, (a >= b)? A: b. For this kind of logic that can be solved by one line of code, you can also use the && and || operators in combination.
Ordinary

String title;
if (isMember(phone)) {
    
    
    title = "会员";
} else {
    
    
    title = "访客";
}

optimization

String title = isMember(phone) ? "会员" : "访客";

Note: For the arithmetic calculation of the package type, care should be taken to avoid the problem of null pointers when unpacking.

7. Use Map data structure + strategy mode + factory mode to handle complex business IF-ELSE

In actual business code, there are often cases where different business logic processing is performed according to a certain Type, which is usually associated with many branch judgments. In addition, a very important point is that this part of the business is judged to have needs for later modification and increase, so how to optimize this part of the business code? A good practical reference is to deal with it through the Map data structure + strategy mode.

For the if-else statement of the mapping relationship, you can use Map to simplify it. In addition, this rule is also applicable to switch statements that simplify the mapping relationship, and use the Map data structure to solve the branching problem.

【ordinary】

 public static String getNameByType(String type) {
    
    
        switch (type) {
    
    
            case "A001":
                return "登录成功";
            case "B001":
                return "密码错误";
            case "C001":
                return "验证码错误";
            case "D001":
                return "短信发送失败";

        }
    }

【optimization】

private static final Map<String, String> MAP = ImmutableMap.<String, String>builder()
            .put("A001", "登录成功")
            .put("B001", "密码错误")
            .put("C001", "验证码错误")
            .put("D001", "短信发送失败").build();


    public static void main(String[] args) {
    
    
        String type = "A001";
        String result = MAP.get(type);

    }

The above code uses Map to store different types of information, but the above code is relatively fixed. On the one hand, it needs to modify the Map data if it is expanded, and on the other hand, it is not suitable for complex business processing.

For this kind of problem, you can use the strategy pattern + factory method to solve the problem of complex business and easy expansion

The detailed code design is no longer stated, see the following blog post for details:
https://juejin.cn/post/6844903974525468680

Overview:
1. Provide a strategy interface
2. Provide a StrategyFactory factory class responsible for storing different branch processing objects in the Map container
3. Use the InitializingBean interface provided by Spring to inject into the container through StrategyFactory when each business processing class is loaded.
4. According to different businesses, obtain objects by obtaining different Beans to perform specific business processing

Guess you like

Origin blog.csdn.net/Octopus21/article/details/114412950