2016-10-03 1 views
0

У меня есть метод, который принимает вход с именем id. Основываясь на идентификаторе возможностей, я выполняю бизнес-реализации, выдвинутые в виде случая коммутатора. У меня есть функциональность, но столкнулась с проблемой, когда отчет о сонаре демонстрирует высокую циклическую сложность около 12-14. Компания, в которой я работаю, использует стандарт 10 как максимальную цикломатическую сложность. Мои соображения состоят в том, что, если мне удастся сломать код на слишком много блоков, читаемость кода будет затронута.Каков наилучший способ обработки кода с помощью операторов if/switch с высокой циклической сложностью?

Примечание: - У меня нет разрешений для изменения правил сонара.

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

// Dependency Injected 
private someService; 

public void processCapability(..., String capabilityId) { 
    switch (capabilityId) { 
     case ORDER_DISPENSED_WITH_SOURCE1: 
      someService.doDispense1(); 
     case ORDER_DISPENSED_WITH_SOURCE2: 
      someService.doDispense2(); 
     case ORDER_REJECTED: 
      someService.doReject(); 
     case ORDER_CANCEL: 
      someService.doCancel(); 
     case ORDER_PURGE: 
      someService.doPurge(); 
      ... 
      default: throw exception 
    } 
} 

Update: Я был в состоянии решить мою проблему, с решением я писал в ответах ниже.

+1

Если есть 12-14 случаев, то 12-14 случаев. Ничто не может с этим поделать, если вы не дублируете дела. Только решение, вероятно, состоит в том, чтобы перестроить ваш общий подход, но я не могу дать вам никаких советов по этому поводу, потому что вы не предоставили никакого кода. Однако правило вашей компании довольно странно. – Zarwan

+0

@ Правила компании Zarwan всегда есть. получается, что управление не понимает код. – nhouser9

+4

«Если мне случится сломать код на слишком много блоков, читаемость кода будет затронута». - обычно читаемость кода отрицательно сказывается, если вы * не разбиваете * на более мелкие блоки (аналогичные методы). Однако они должны иметь хорошее имя, которое описывает, что делает этот метод, и имеет четкую, единую функцию. –

ответ

0

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

// Dependency Injected 
private someService; 

public void processCapability(..., String capabilityId) { 

    Boolean isCapabilityProcessed = processDispenseCapabilities(...) || processUpdateCapabilities(..); 

    if(isCapabilityProcessed) { 
    throw exception("Invalid Capability"); 
    } 
} 

private Boolean processDispenseCapabilities(..,String capabilityId) { 

    Boolean result = false; 

    switch (capabilityId) { 
     case ORDER_DISPENSED_WITH_SOURCE1: 
      someService.doDispense1(); 
      result = true; 
     case ORDER_DISPENSED_WITH_SOURCE2: 
      someService.doDispense2(); 
      result = true; 
     case ORDER_REJECTED: 
      someService.doReject(); 
      result = true; 
      ... 
     default: //do nothing 
    } 

    return result; 
} 

private Boolean processUpdateCapabilities(..,String capabilityId) { 
    Boolean result = false; 

    switch (capabilityId) { 
     case ORDER_CANCEL: 
      someService.doCancel(); 
      result = true; 
     case ORDER_PURGE: 
      someService.doPurge(); 
      result = true; 
      ... 
     default: //do nothing 
    } 

    return result; 
} 
1

Существует множество способов избежать крупных заявлений if-else.

Возможно, наиболее распространенными узорами являются template method pattern и strategy pattern.

Поскольку вы не указали какой-либо код, трудно помочь вам снизить цикломатическую сложность, но я абсолютно уверен, что есть способ избежать этих if-else-s.

Я предлагаю вам прочитать немного о теме; Я приведу вам некоторые источники я нашел полезный:

  1. Using strategy to replace if else
  2. Using command pattern to replace conditional logic
  3. Я призываю вас использовать перечисления, они более удобны в использовании в условной логике, чем вы думаете: using enums instead of switch
  4. Кроме того, это хорошо, чтобы знать о различных шаблонов проектирования, может быть, вы можете найти подходящий один here

Также читаемый код означает, что он легко под стоять. Я согласен с комментарием @Erwin Bolwidt, если вы создадите больше методов с хорошими именами, его будет легче читать. Чтобы узнать больше о теме, прочитайте книгу «Чистый код» Роберта К. Мартина.

+0

Я рассмотрел реализацию Стратегии. Но я чувствовал, что это будет излишне, и сделать код еще сложнее читать для других разработчиков. – daemon54

+0

Ну, я думаю, что для начинающих это сложнее, но в конце, когда вам нужно будет добавить один или несколько случаев в существующие if-s, это будет незабываемый беспорядок. – abbath

0

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

@SuppressWarnings("squid:MethodCyclomaticComplexity") 
+0

Я не хочу подавлять, так что это не вариант, который я могу использовать. – daemon54

1

Я предлагаю вам реорганизовать этот переключатель заявление (который является кодом запаха) с помощью полиморфизма.Возможный способ сделать это что-то вроде этого:

public interface Order { 
    void processCapability(...); 
} 

public final class RejectedOrder implements Order { 
    private final SomeService someService; 

    public RejectedOrder(SomeService someService) { 
     this.someService = someService; 
    } 

    @Override 
    public void processCapability(...) { 
     someService.doReject(); 
    } 
} 

public final class CancelledOrder implements Order { 
    private final SomeService someService; 

    public RejectedOrder(SomeService someService) { 
     this.someService = someService; 
    } 

    @Override 
    public void processCapability(...) { 
     someService.doCancel(); 
    } 
} 

Более полезные ресурсы говорить о 'переключателя запаха':

+0

Один вопрос. Как я узнаю, что эти возможности входят в классы Отклонения/Отмена/Распространение, которые реализуют Заказ? – daemon54

+1

@ daemon54 Каждый случай коммутатора может быть извлечен в отдельный класс, реализующий «Заказ». – Spotted

Смежные вопросы