daemon54 daemon54 - 2 months ago 10
Java Question

What is the best way to handle code with if/switch statements having high cyclomatic complexity?

I have a method that takes an input called capability id. Based on the capability id, I execute the business implementations put forward in form of a switch case. I have my functionality working, But came across a problem where the sonar report is showing high cyclomatic complexity around 12-14. The company I work for, uses a standard of 10 as the max cyclomatic complexity. My considerations is that, If I happen to break the code into too many block, the code readability is getting affected.

Note:-
I don't have permissions to change sonar rules.

Unfortunately, I can't share the code. The code would be in the following way though,

// 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: I was able to resolve my problem, with a solution I posted in below answers.

Answer

I have figured one way to handle the big if/switch statements. Based on the ideas, I got from everyone of you. I compiled into a simple solution that is easy to understand and modify, also handles the complexity part. Please find my solution below,

// 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;
}