Мне нужно исправить проблему с сонаром, связанную с большой цикломатической сложностью, но до сих пор не знаю, как это сделать.
Код состоит из большого количества операторов 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, некрасив. Однако, поскольку он сопоставляет только входные параметры с экземпляром enum и ничего больше, я думаю, что это, вероятно, достаточно хорошее решение проблемы, которую он решает. Это особенно сложно читать и понимать? Будет ли изменение правил, которые он моделирует, сделать легко или сложно? Даже для новичка в команде? Это вопросы, которые должны привести к решению изменить этот метод, а не просто «Sonarqube говорит, что это слишком много».




Вы можете определить интерфейс, скажем, 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();
}
Таким образом можно было избежать «если».
Надеюсь это поможет!
создать несколько методов и разделить if-else в этих методах