preface

Some time ago when I was reading the code written by others, I found that there were a lot of if-else statements nested in several layers in the body of some business-related methods. First of all, I don’t personally discourage writing if-else statements, and I have to say, a lot of times, if you’re writing logic and you’re using if-else, it looks pretty straightforward, but if you’re abusing if-else, you’re nesting multiple layers, Each case also contains a lot of logic, so using if-else is not worth the cost in terms of readability. And in some cases, you may not need as much if-else, or you can use other encoding methods to achieve reduced if-else effects.

There are many ways to reduce the use of if-else, such as the design pattern-level policy pattern or the chain of responsibility pattern. And here to share with you some personal daily coding process often used, relatively simple, from the level of coding habits, to reduce some unnecessary if-else use. Because I am only a rookie, if there is a wrong place to write, please criticize correct.

Some encoding that reduces if-else

Method 1: Return in advance

Let’s start with a code example:

if (condition1) {
    if (condition2) {
        return getSomething();
    } else {
        return 0; }}else {
    return 0;
}
Copy the code

The modified code is as follows:

// It is best to describe the logic judged by this flag with additional comments
booleanflag = ! condition1 || (condition1 && ! condition2)if(flag) {
	return 0;
}

if (condition1 && condition2) {
    return getSomething();
} 
Copy the code

If there is logic that is known to return a fixed value under certain conditions, you can extract this logic into a separate if-else block and put it in front of other if-else blocks. When this condition is met, you can return the fixed value in advance. The most immediate effect of this approach is to reduce the amount of nesting of if-else.


Method 2: Use the ternary operator

Here is an example of a business scenario:

Query the list of image urls for a comment (if any, the list of image urls for the comment is stored in the comment table as a JSON array string)

The code before modification is as follows:

Comment comment = getById(commentId);

if (Objects.isNull(comment)) {
    throw new RuntimeException("Comment does not exist or has been deleted");
}

String imgListStr = comment.getImgList();
if(StringUtils.isEmpty(imgListStr)) {
    return null;
}

return JSON.parseArray(imgListStr, String.class);
Copy the code

Revised:

Comment comment = getById(commentId);

if (Objects.isNull(comment)) {
    throw new RuntimeException("Comment does not exist or has been deleted");
}

String imgListStr = comment.getImgList();
return StringUtils.isEmpty(imgListStr)) ?
    null : JSON.parseArray(imgListStr, String.class);
Copy the code


Method 3: Use Assert assertions

In the process of writing business code, if you need to judge some specific conditions, and when the conditions are not met, you need to throw an exception. For this scenario, in addition to using the if approach in the trinary operator example above, you can also use the Assert tool class provided by the Spring Framework.

Common apis include:

  • isTrue(boolean expression , String message) :expressio == false“, will throw an exception, exceptionmessageIs the second input parameter;
  • void notNull(@Nullable Object object, String message) :Same as above, whenobject == nullIs thrown an exception.
  • void notEmpty(@Nullable Collection<? > collection, String message) :As above, when the set object isnullOr if the collection element is empty, an exception is thrown.
  • .

There are many other methods, you can directly look at the source parsing, of course, in fact isTrue() is sufficient, if you need to be more semantic, you can use the corresponding API.

Code before modification:

if (Objects.isNull(comment)) {
    throw new RuntimeException("Comment does not exist or has been deleted");
}
Copy the code

Modified code:

 Assert.isTrue(Objects.nonNull(comment),"Comment does not exist or has been deleted");
 Assert.notNull(comment,"Comment does not exist or has been deleted");
Copy the code

Now Assert tool method can only throw a single a Java exception. Lang. IllegalArgumentException, if you need to customize the exception thrown by the, then this method is not applicable.


Option 4: Use Optional

Optional is a new java8 feature. It is used to verify the null value of an object and perform subsequent operations, such as throwing exceptions and null replacement.

Among them, I often use several methods:

  • Static

    Optional

    ofNullable(T value) : wrap the object with Optional;

  • T orElse(T other) :The object in Optional isnullReturns the object of the input parameter.
  • T orElseGet(Supplier<? extends T> other) :The object in Optional isnullWhen to return toSupplierThe value provided;
  • T orElseThrow(Supplier<? extends X> exceptionSupplier) :The object in Optional isnullWhen thrownsupplierCustom exception provided

Code examples:

Message message1 = Optional.ofNullable(getById(messageId))
    .orElseThrow(() -> new RuntimeException("The message does not exist!));

Message message2 = Optional.ofNullable(getById(messageId))
    .orElse(new Message());

Message message3 = Optional.ofNullable(getById(messageId))
    .orElseGet(Message::new);
Copy the code

Since I need to perform null value judgment more scenarios in daily life, when the data query is completed from the database, I need to perform null value judgment on the query results. Since the persistence layer framework used by my company is Mybatis, unlike the default JPA of Spirng Boot 2.x, the DAO layer method supports the return value of Optional, so if Optional is needed here, The query results can only be wrapped manually using the first method listed above.

Of course, IDEA has already provided us with hotkeys for this packaging mode, as shown in the figure below:

conclusion

Here are some ways to reduce if-else coding habits. Among these ways, I personally think the most obvious effect is the first way to return early, many times, return early can also be very good to reduce the complexity of a piece of code.

Of course, if you have to use a lot of if-else to control the logic, it’s a good idea to comment each condition.