繁体   English   中英

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

[英]Improve the cyclomatic complexity code for if-else statements

我在遇到循环复杂性问题的方法中有一块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
    }

编辑 :如前所述,您已经检查了可以抛出的Exception 方法中的参数。 由于Runnable并未声明它会引发Exceptions并且也不接受您必须创建自己的FunctionalInterface任何参数(请单击此处查看其真正含义):

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

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


您可以创建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:

圈复杂度是一个问题:确实是循环

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

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

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

您可以使用谓词和函数功能接口通过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();

要么

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM