Home > Enterprise >  How to fix SonarLint Cognitive Complexity Error for multiple If-Else conditions
How to fix SonarLint Cognitive Complexity Error for multiple If-Else conditions

Time:10-14

I have to write a lot of conditions, but SonarLint is giving me error, asking to refactor the method to reduce its cognitive complexity.

How to resolve this. I tried switch-case, but that is also giving the same error.

public enum ExampleEnum {
    UNKNOWN(-1),
    D0_D100(0),
    D100_D200(100),
    D200_D300(200),
    D300_D400(300),
    D400_D500(400),
    D500_D600(500),
    D600_D700(600),
    D700_D800(700),
    D800_D900(800),
    D900_D1000(900);
    
    private int score;
    
    ExampleEnum(int score) {
        this.score = score;
    }
}

public static ExampleEnum getScoreType(Integer score) {
    if (Objects.isNull(score) || score < D0_D100.score) {
        return UNKNOWN;
    } else if (score >= D0_D100.score && score < D100_D200.score) {
        return D0_D100;
    } else if (score >= D100_D200.score && score < D200_D300.score) {
        return D100_D200;
    } else if (score >= D200_D300.score && score < D300_D400.score) {
        return D200_D300;
    } else if (score >= D300_D400.score && score < D400_D500.score) {
        return D300_D400;
    } else if (score >= D400_D500.score && score < D500_D600.score) {
        return D400_D500;
    } else if (score >= D500_D600.score && score < D600_D700.score) {
        return D500_D600;
    } else if (score >= D600_D700.score && score < D700_D800.score) {
        return D600_D700;
    } else if (score >= D700_D800.score && score < D800_D900.score) {
        return D700_D800;
    } else if (score >= D800_D900.score && score < D900_D1000.score) {
        return D800_D900;
    } else {
        return D900_D1000;
    }
}

CodePudding user response:

Put the logic into a loop. something like:

public static ExampleEnum getScoreType(Integer score) {
    if (Objects.isNull(score) || score < D0_D100.score) {
        return UNKNOWN;
    for (int i =0; i< ExampleEnum.values().length-1;i  ) {
        if (ExampleEnum.values()[i].score <= score && ExampleEnum.values()[i 1].score > score )
            return ExampleEnum.values()[i];
    }
    return D900_D1000;
}

CodePudding user response:

You can use of the Stream API to remove this redundancy.

For that, you make use of the fact that the natural order of your enum-members reflects the order of the corresponding score.

As the source of the stream, you can use an array returned by the values() call or an EnumSet (which a specialized ordered collection) generated via EnumSet.allOf().

While iterating over the enum-members we need to find the first constant which score is equal or less to the given score. Because score property of your enum represent the lower boundary of the range, only one condition would be sufficient to find out if the given score falls into the range corresponding to a particular enum-member.

This logic can be expressed by using combination of operations filter() findFirst():

public static ExampleEnum getScoreType(Integer score) {
    if (score == null || score < ExampleEnum.D0_D100.score) {
        return ExampleEnum.UNKNOWN;
    }
    
    return EnumSet.allOf(ExampleEnum.class).stream()
        .filter(e -> score >= e.score)
        .findFirst()
        .orElse(ExampleEnum.D900_D1000);
}

Note: you're not checking if the given score exceeds the maximum range, in such case the last enum-constant would be returned. But since its name D900_D1000 signifies that it represents a limited range values, you might want to add this check.

  • Related