Действительно ли использование карты действительно снижает цикломатическую сложность?

Предположим, что у меня есть оригинальный метод ниже.

public String someMethod(String str) {
    String returnStr;
    if("BLAH".equals(str)) { 
       returnStr="ok";
    } else if ("BLING".equals(str)) {
       returnStr="not ok";
    } else if ("BONG".equals(str)) {
       returnStr="ok";
    }
    return returnStr;
}

Преобразовывает ли снизу действительно уменьшает CC?

Map<String, String> validator = new HashMap<String,String>();
validator.put("BLAH","ok");
validator.put("BLING","not ok");
validator.put("BONG","ok");

public String someMethod(String str) {
  return validator.get(str);
}

Ответы

Ответ 1

Да, в вашем случае. Говоря простыми словами, циклическая сложность представляет собой ряд линейно-независимых способов достижения конца фрагмента кода от начальной точки. Таким образом, любой условный оператор увеличивает CC вашего кода.

(если вопрос OP каким-то образом связан с тегом testing). Однако уменьшение CC не уменьшает количество unit test, которое должно быть записано для покрытия вашего кода: CC дает вам только нижнюю границу счетчика тестов. Для хороших тестов модуляции покрытия должны охватывать все конкретные случаи, а во втором случае вы не уменьшаете это количество конкретных случаев, вы только делаете свой код более удобочитаемым.

Ответ 2

Да, поскольку циклическая сложность определяет число линейных независимых путей в графе потока управления плюс один. В вашем втором примере есть только один путь, первый имеет несколько путей через ветки if. Однако, похоже, что цикломатическая сложность действительно является проблемой здесь. Вы можете подставить свой метод таким образом, чтобы сделать его более читаемым:

public String someMethod(String str) {

    switch(str) {
        case "BLAH":
        case "BONG": return "ok";
        case "BLING": return "not ok";
        default: return null;
    }

}

Ответ 3

Короткий ответ: да, использование Hashmap в вашем случае уменьшает Cyclomatic complexcity.

Подробный ответ: Цикломатическая сложность по википедии

Это количественная мера количества линейно независимых путей через программный исходный код.

Существуют различные способы решения дел if-else. Операторы if-else делают код менее читаемым, его трудно понять. Эти if-else также плохи, поскольку каждый раз, когда вы добавляете/удаляете/изменяете в случаях, вам необходимо изменить существующие файлы кода, где ваша другая бизнес-логика остается такой же, и из-за изменения этих файлов вам необходимо протестировать их все снова. Это приводит к проблемам с обслуживанием, а также во всех местах, где нам необходимо следить за случаями. Аналогичные проблемы существуют и с операторами switch, хотя они мало читаемы.

То, как вы использовали, также уменьшает различные логические пути выполнения. Другой альтернативный подход выглядит следующим образом.

Вы можете создать интерфейс, скажем IPair. Пусть этот интерфейс определяет абстрактный метод public String getValue(); Позволяет определить разные классы для каждого имеющегося у нас случая и BlahMatch.java, Bling.java and Bong.java реализовать IPair, а в реализации метода getValue() вернуть соответствующий String.

public String someMethod(IPair pair) {
    return pair.getValue();
}

Преимущество вышеуказанного подхода заключается в том, что если у вас есть несколько новых папок, вы все равно сможете создать новый класс и легко передать объект своего нового класса, просто вам нужно, чтобы ваш класс обеспечивал реализацию для IPair.