About Patroklos Papapetrou

Patroklos is an experienced JavaEE Software Engineer and an Agile enthusiast seeking excellence in software quality. He is also co-Author of the Sonar in Action book, and contributor of several Sonar plugins.

Avoiding Many If Blocks For Validation Checking

There are cases that we want to validate input data before we send them to business logic layer for processing, computations etc. This validation, in most cases, is done in isolation or it might include some cross-checking with external data or other inputs. Take a look at the following example that validates user input for registration data.
 
 
 
 
 
 
 

public void register(String email, String name, int age) {
 String EMAIL_PATTERN = 
 "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
 + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
 Pattern pattern = Pattern.compile(EMAIL_PATTERN);
 
 List<String> forbiddenDomains = Arrays.asList("domain1", "domain2");
 if ( email == null || email.trim().equals("")){
   throw new IllegalArgumentException("Email should not be empty!");
 }
 
 if ( !pattern.matcher(email).matches()) {
   throw new IllegalArgumentException("Email is not a valid email!");
 }
 
 if ( forbiddenDomains.contains(email)){
   throw new IllegalArgumentException("Email belongs to a forbidden email");
 }
 
 if ( name == null || name.trim().equals("")){
   throw new IllegalArgumentException("Name should not be empty!");
 }
if ( !name.matches("[a-zA-Z]+")){
   throw new IllegalArgumentException("Name should contain only characters");
 }
if ( age <= 18){
   throw new IllegalArgumentException("Age should be greater than 18");
 }
// More code to do the actual registration
}

The cyclomatic complexity of this method is really high and it might get worse if there are more fields to validate or if we add the actual business logic. Of course we can split the code in two private methods ( validate, doRegister ) but the problem with several if blocks will be moved to the private methods. Besides this method is doing more than one thing and is hard to test. When I ask junior developers to refactor this code and make it more readable, testable and maintainable they look at me like an alien :”How am I supposed to make it simpler. How can I replace these if blocks?” Well here’s a solution that works fine, honors the Single Responsibility Pattern and makes the code easier to read.

To better understand the solution, think each of these if blocks as a validation rule. Now it’s time to model these rules.

First create an interface with one method. In Java 8 terms, it’s called a functional interface, like the following.

public interface RegistrationRule{
 void validate();
}

Now it’s time to transform each validation check to a registration rule. But before we do that we need to address a small issue. Our interface implementation should be able to handle registration data but as you see we have different types of data. So what we need here is to encapsulate registration data in a single object like this :

public class RegistrationData{
 private String name;
 private String email;
 private int age;
// Setters - Getters to follow
}

Now we can improve our functional interface:

public interface RegistrationRule{
void validate(RegistrationData regData);
}

and start writing our rule set. For instance let’s try to implement the email validation.

public class EmailValidatationRule implements RegistrationRule{
 private static final String EMAIL_PATTERN = 
 "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
 + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
 private final Pattern pattern = Pattern.compile(EMAIL_PATTERN);
@Override
 public void validate(RegistrationData regData) {
 if ( !pattern.matcher(regData.email).matches()) {
   throw new IllegalArgumentException("Email is not a valid email!");
 }
}

It’s clear that we have isolated in the above class the email validation. We can do the same for all rules of our initial implementation. Now we can re-write our register method to use the validation rules.

List<RegistrationRule> rules = new ArrayList<>();
 rules.add(new EmailValidatationRule());
 rules.add(new EmailEmptinessRule());
 rules.add(new ForbiddenEmailDomainsRule());
 rules.add(new NameEmptinessRule());
 rules.add(new AlphabeticNameRule());
 
 for ( RegistrationRule rule : rules){
  rule.validate(regData);
 }

To make it even better we can create a Rules class using the Factory pattern and a static method get() that will return the list of rules. And our final implementation will look like this

for ( RegistrationRule rule : Rules.get()){
  rule.validate(regData);
}

Comparing the initial version of our register method to the final one leaves room for doubts. Our new version is more compact, more readable and of course more testable. The actual checks have been moved to separate classes (which are easy to test also) and all methods do only one thing (try to always keep that in mind).

Reference: Avoiding Many If Blocks For Validation Checking from our JCG partner Patroklos Papapetrou at the Only Software matters blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

2 Responses to "Avoiding Many If Blocks For Validation Checking"

  1. Sankalp says:

    This is a good example to have a maintainable and test friendly coding fashion for same old problem. Every developer come across such situation when they don’t like a bunch of ‘if’s but though have to have it.
    Thanks for the share.

  2. ramesh says:

    Hi

    TO reduce the number of if else blocks , we are creating the related classes which contains the functionality of validation , but these leads to increase in the number of classes , as per your design each validation / field leads to one class. is it fine having like this ?

Leave a Reply


seven − 6 =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close