Уменьшить проблему цикломатической сложности

Мне нужно исправить проблему с сонаром, связанную с большой цикломатической сложностью, но до сих пор не знаю, как это сделать.

Код состоит из большого количества операторов if, которые проверяют параметры, поступившие в метод, и решают, какое значение перечисления создать.

Вот, например, фрагмент кода:

      public ProductType createProductType(String val1, String val2, String val3) {
        if (PRODUCT_MODEL.equals(val1) && PRODUCT_TYPE.equals(val2) {
            return ProductType.SOAP;
        }
        if (PRODUCT_MODEL.equals(val1) || val3.equals(SWAP)) {
            return ProductType.STRING;
        }
}

И так далее.. Как видите, я не могу написать это, используя случай переключателя, потому что проверяется более одной переменной. Также я не могу создать статическую карту с ключами типа Predicate, потому что критерии сравнения приходили в метод динамически. Поэтому я не могу понять, как устранить эти операторы «если».

Какие-либо предложения?

РЕДАКТИРОВАТЬ

если разделить его на методы для каждого типа продукта, как тогда я буду проверять, когда тип продукта создается? Я имею в виду, что у меня есть

ProductType productType = null;
productType = tryParseSoap;
if (Objects.nonNull(productType)) {
    return productType;
}
productType = tryParseString;
if (Objects.nonNull(productType)) {
    return productType
}

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

создать несколько методов и разделить if-else в этих методах

Sunny 21.09.2018 14:48

Может быть, три переключателя, один внутри другого?

DodgyCodeException 21.09.2018 14:53

Конечно, большой метод, усеянный подобными if / else, некрасив. Однако, поскольку он сопоставляет только входные параметры с экземпляром enum и ничего больше, я думаю, что это, вероятно, достаточно хорошее решение проблемы, которую он решает. Это особенно сложно читать и понимать? Будет ли изменение правил, которые он моделирует, сделать легко или сложно? Даже для новичка в команде? Это вопросы, которые должны привести к решению изменить этот метод, а не просто «Sonarqube говорит, что это слишком много».

KevinLH 21.09.2018 14:57
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
416
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете определить интерфейс, скажем, ProductTypeCreator

public interface ProductTypeCreator {

    boolean isApplicable(String val1, String val2, String val3);

    ProductType create(String val1, String val2, String val3);

}

Затем создайте реализацию для каждого конкретного случая if. Затем у вас могут быть создатели List и рефакторинг вашего метода до чего-то вроде.

public ProductType createProductType(String val1, String val2, String val3) {
    // this should already be instantiated
    List<ProductTypeCreator> creators;
    return creators
       .stream()
       .filter(creator -> creator.isApplicable(val1, val2, val3))
       .map(creator -> creator.create(val1, val2, val3))
       .findFirst()
       .get();
}

Таким образом можно было избежать «если».

Надеюсь это поможет!

Другие вопросы по теме