改进if-else语句的圈复杂度代码

时间:2019-05-29 08:49:15

标签: java cyclomatic-complexity

在我遇到循环复杂性问题的方法中,我有一个if-else语句块。我已经尝试过使用switch语句,但是问题仍然存在。

if (fileName.startsWith(HwErrorsEtlConstants.MR_RAW_GRADIENT_ERRORS)) {
    method1()...
} else if (fileName.startsWith(HwErrorsEtlConstants.MR_RAW_PFEI_ERRORS)) {
    method2()...
} else if (fileName.startsWith(HwErrorsEtlConstants.MR_RAW_RFAMP_ERRORS)) {
    method3()...
} and so on...

public static void method1(IOutputWriter writer, String fileName, InputStream fileInputStream) throws IOException {
        //logic for the method
    }

3 个答案:

答案 0 :(得分:3)

编辑:如前所述,您已经检查了Exception个可以在您的方法中自变量引发的内容。由于Runnable并没有声明可以抛出Exceptions并且不接受任何参数,因此您必须创建自己的FunctionalInterface(单击here来查看它们的含义)确实是):

public interface ThrowingRunnable {
    void run(IOutputWriter writer, String fileName, InputStream fileInputStream) throws IOException;
}

然后,您只需在下面我先前建议的代码中将Runnable替换为ThrowingRunnable,就可以了。


您可以创建HwErrorsEtlConstants到特定方法的映射(使用Java 8):

static final Map<String, Runnable> MAPPING;
static {
    Map<String, Runnable> temp = new HashMap<>();
    temp.put(HwErrorsEtlConstants.MR_RAW_GRADIENT_ERRORS, this::method1);
    temp.put(HwErrorsEtlConstants.MR_RAW_PFEI_ERRORS, this::method2);
    temp.put(HwErrorsEtlConstants.MR_RAW_RFAMP_ERRORS, this::method3);
    MAPPING = Collections.unmodifiableMap(temp);
}

然后在您的方法中,可以使用Java 8中也引入的Stream

// Optional indicates a potentially absent value, it's just a wrapper around a Runnable
Optional<Runnable> optional = MAPPING
    // create a Stream from the entries
    .entrySet().stream()
    // keep the items that match the condition and drop every other
    .filter(e -> filename.startsWith(e.getKey()))
    // we had Map.Entry<String, Runnable>, but now we only need the value e.g. the Runnable
    .map(Map.Entry::getValue)
    // short circuit, e.g. we only want the first value that matches
    .findFirst();

// checks if anything is present, this is used as the MAPPING "could" be empty
if(optional.isPresent()) {
    // unpack the value and call it with arguments
    optional.get().run(aWriter, someFileName, anInputStream);
} else {
    // nothing matched, throw error or log etc.
}

尽管如上所述,您当前的解决方案确实不错,但我想您正在使用Sonar进行代码分析。有时,Sonar只会产生误报,因此您也可以放心地忽略它们。

进一步阅读以帮助您理解Java 8:

答案 1 :(得分:2)

cyclomatic complexity是一个问题:确实是周期

然后使用不面向对象的if / switch对属性进行分割。它还可能违反关注点分离:拥有许多处理完全不同的较小方面的方法。

如果字段数较大,并且行数较大,请考虑提取处理一个方面的类。

为降低循环复杂性,请检查以控制调用者的流程,同一呼叫的重复,实用的重复代码。然后尝试(重新)移动循环。 最好是可以将各个周期放在一起的时间;并处理列表/集合/流。

答案 2 :(得分:1)

您可以使用谓词和函数功能接口通过Java 8方法解决此问题。您必须通过谓词放置所有条件,然后在Function中添加条件匹配时需要执行的实现。

Map<Predicate,Function<String,String>> map = new HashMap<>();

    Predicate<String> p = (fileName)->fileName.startsWith(HwErrorsEtlConstants.MR_RAW_GRADIENT_ERRORS);

  Function<String,String> method = (input)->{ return "output";}; 

   map.put(p,method);
    Optional<String> result =
    map.entrySet()
    .stream()
    .filter(entry->entry.getKey().test(fileName))
    .map(entry->entry.getValue().apply())
    .findFirst();

OR

  map.entrySet()
    .stream()
    .filter(entry->entry.getKey().test(fileName))
    .forEach(entry->entry.getValue().apply());