Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OOP-Design for validating user input

Currently, I try to design some things with OO principles in mind. So let's say, before processing user input, I need to validate it. According to OO, a separate Validator class would be the correct way. This would look as follows:

    public class Validator{
      public void validate(String input) throws ValidationException{
        if (input.equals("")) throw new ValidationException("Input was empty");
      }
    }

Then, my processing class, which got the validator object before via dependency injection would call validator.validate(input)

A good point about this design is, that

  1. My processing class can get a mock for the validator via DI which makes testing easier
  2. The Validator class can be tested independently

However, my doubts are in the design of the Validator. According to OO, it misses some kind of state. With this design, it is as util class and the validate method could be static. And I read a lot of times that (static) Util classes are bad OO design. So, how can this be done with more OO while keeping the two advantages I mentioned?

PS.: Maybe, OO is simply a bad solution for this kind of problem. However, I would like to see how the OO solution would look like and form my own opinion.

like image 464
Niklas Avatar asked Oct 28 '22 21:10

Niklas


2 Answers

The validator in your example doesn't have a state (and doesn't need any), but another validator could require one (say with a format):

Example:

public class RegExValidator {
    private Pattern pattern;

    public RegExValidator(String re) {
        pattern = Pattern.compile(re);
    }

    public void validate(String input) throws ValidationException {
        if (!pattern.matcher(input).matches()) {
            throw new ValidationException("Invalid syntax [" + input + "]");
        }
    }
}
like image 102
Maurice Perry Avatar answered Oct 31 '22 19:10

Maurice Perry


Concentrating on the OOP aspect of your question (rather than the question if an Exception is the correct way to handle your validation):

Why have a single validator?

interface Validator<T> {
    void validate(T toValidate) throws ValidationException;
}

would enable you to write classes that can validate any class T and be very testable. Your validator would look like this:

class EmptyStringValidator implements Validator<String> {
    public void validate(String toValidate) {
        if(toValidate == null || toValidate.isEmpty()) throw new ValidationException("empty!!!");
    }
}

and you could test it very easily. In fact, if you're using Java 8, this would be a functional interface, so a single utility class could host several validators:

class ValidationUtil {
    public static void emptyString(String val) // same code as above
}

and ValidationUtil::emptyString would implement Validator<String>. You would combine several validators with a composite pattern.

You could also have a validator with a state if that's what you need...

class ListIsSortedValidator implements Validator<Integer> {
    private int lastInt = Integer.MIN_VALUE;
    public void validate(Integer val) throw ValidationException {
        if (val < lastInt) throw new ValidationException("not sorted");
        lastInt = val;
    }
}

That you could use to for instance validate a list:

List<Integer> list = createList();
Validator<Integer> validator = new ListIsSortedValidator();
list.forEach(validator::validate);
like image 29
daniu Avatar answered Oct 31 '22 19:10

daniu