Refactor multiple ifs in create specification

67 Views Asked by At

How can I refactor the following method in order to reduce complexity?

protected Specification<Test> createSpecification(TestCriteria criteria) {
        Specification<Test> specification = Specification.where(null);
        if (criteria != null) {
            if (criteria.getId() != null) {
                specification = specification.and(buildRangeSpecification(criteria.getId(), test_.id));
            }
            if (criteria.getCustomerName() != null) {
                specification = specification.and(buildStringSpecification(criteria.getCustomerName(), Test_.customerName));
            }
            if (criteria.getAddress() != null) {
                specification = specification.and(buildStringSpecification(criteria.getAddress(), Test_.address));
            }
(...)

return specification;
}

The issue is that sonar is complaining about: Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Thanks!

2

There are 2 best solutions below

0
Hansjörg Hofer On BEST ANSWER

Or

Use Builder Pattern... Create a builder that allows adding specifications:

public class TestSpecificationBuilder {

  private Specification<Test> spec;
  
  public TestSpecificationBuilder() {
    spec = Specification.where(null);  
  }
  
  public TestSpecificationBuilder withId(Long id) {
    spec = spec.and(buildIdSpecification(id));
    return this;
  }  
  
  public TestSpecificationBuilder withName(String name) {
    spec = spec.and(buildNameSpecification(name));
    return this; 
  }
  
  public Specification<Test> build() {
    return spec;
  }
}

So the main method just builds and returns the specification.

2
Hansjörg Hofer On

Consider inverting some of the if conditions and using early returns.

protected Specification<Test> createSpecification(TestCriteria criteria) {
        Specification<Test> specification = Specification.where(null);
        if (criteria == null) return specification;
     
       // split into methods
       addIdSpecification(criteria.getId(), specification);
       addStringSpecification(criteria.getCustomerName(), Test_.customerName, specification);
       addStringSpecification(criteria.getAddress(), Test_.address, specification);
       
       // Add other criteria as needed
(more)

return specification;
}


private void addIdSpecification(Long id, Specification<Test> specification) {
    if (id == null) return;
    specification = specification.and(buildRangeSpecification(id, test_.id));
   
}

...

But the Cognitive Complexity depends on more factors like include depth an much more...