Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reduce cyclomatic complexity?

I'm working on a class which sends a RequestDTO to a Web Service. I need to validate the request before it is sent.

The request can be sent from 3 different places and there are different validation rules for each "requesttype", e.g. request1 must have name and phonenumber, request2 must have address, etc)

I have a DTO which contains a long list of fields (name, address, city, phonenumber, etc.) and it is the same DTO sent no matter which type of request it is.

I have created 3 different validation methods and based on the type the appropriate method is called.

In each of these methods I have a long list of if-else's to check for the fields that are necessary for each request type.

private void validateRequest1(Request request) {     StringBuilder sb = new StringBuilder();     if (null == request) {         throw new IllegalArgumentException("Request is null");     }     if (isFieldEmpty(request.getName())) {  *see below         sb.append("name,"));     }     if (isFieldEmpty(request.getStreet())) {         sb.append("street,"));     }     ... 

isFieldEmpty() checks the string for null and isEmpty() and returns a boolean

This gives me a cyclomatic complexity of 28 in one of those methods so my question is.. is it possible to reduce this complexity? - if so, how would I go about doing so?

Ultimately I need to check a lot of fields and I cannot see how this can be done without lots of checks :/

like image 600
Linora Avatar asked May 07 '13 11:05

Linora


People also ask

What is cyclomatic complexity and how do you reduce it?

Cyclomatic complexity refers to the number of possible execution paths inside a given piece of code—for instance, a function. The more decision structures you use, the more possible branches there are for your code. Cyclomatic complexity is especially important when it comes to testing.

How can cyclomatic complexity be reduced in a switch case?

Avoid use of switch/case statements in your code. Use Factory or Strategy design patterns instead. Complexity of 8 (1 for each CASE and 1 for method itself). Refactoring using Factory design pattern and complexity changed to 1.

What cyclomatic complexity is too high?

Consequences: A high cyclomatic complexity for a particular function means that the function will be difficult to understand, and more difficult to test. That in turn means functions with a cyclomatic complexity above 10 or 15 can be reasonably expected to have more undetected defects than simpler functions.


2 Answers

An easy way is to promote the check into a separate method:

private String getAppendString(String value, String appendString) {     if (value == null || value.isEmpty()) {         return "";     }     return appendString; } 

And then you can use this method instead of the if blocks:

sb.append(getAppendString(request.getStreet(), "street,"); 

This will reduce complexity from 28 down to 3. Always remember: high complexity counts are an indication that a method is trying to do too much. Complexity can be dealt with by dividing the problem into smaller pieces, like we did here.

like image 193
EmirCalabuch Avatar answered Sep 20 '22 21:09

EmirCalabuch


Another approach would be to enforce that contract in the Request object itself. If a field is required or can't be null, say so when the Request is created.

Create the Request in such a way that it's 100% valid and ready to go when the constructor exists.

I'd also create that String version in the Request toString() method. It should know how to render itself.

like image 23
duffymo Avatar answered Sep 21 '22 21:09

duffymo