Java – Designing validation classes

datadesignjavavalidation

This is a follow-up of this question. I decided to implement what the accepted answer suggests, however, I realized I also needed individual public methods for each member the entity to be validated has, so it is not only validated as a whole, but also its members as separate units:

This is what was suggested:

public interface Validable {
    public void setValidator(Validator validator);
    public void validate() throws ValidationException;
    public List<String> getMessages();
}

public interface Validator<T> {
    public boolean validate(T e);
    public List<String> getValidationMessages();
}

public class EventValidator implements Validator<Event> {
    public boolean validate(Event e) {
        // validate each member here, as well as the entity as a whole
        return isValid;
    }

    // etc...
}

But now I need public methods for each member of the Event. The reason is to use each of these methods in the Event setters and methods with a similar purpose, like adding items to a list or a dictionary, initializing data, modifying data, etc.

So I would need something like:

public class EventValidator implements Validator<Event> {
    // Validates the whole object
    public boolean validate(Event e) {
        // ...
    }

    public boolean validatePlayers() {
        // ...
    }

    public boolean validateCourts() {
        // ...
    }

    public boolean validateMatches() {
        // ...
    }
}

This first thing I can see I need is to turn that Event e parameter in the "main" validate(Event e) method into a member variable so the rest of the methods can access them. But this violates the whole point of this design, which was decoupling the entity from the validator.

What would be the most fitting design to cover my needs? I wouldn't care if I had to start from scratch and totally forget about the current design.

Best Answer

I think it might help to realize that Validable and Validator are interfaces that relate to the validation of a single entity, and that you are now trying to force the validation of a composite of entities into this design. Your Validator should only validate the event, do not try to use it to validate the rules for creating the event. Make a distinction between the event and the rules for creating the event.

Once you gain this insight you have many options going forward.

It seems you are modeling a tennis match. In that case, an event should probably be created by some kind of match-maker. (It might suit you to use the builder pattern?) What you are actually wanting to validate is not the event, but the steps in the process of building an event. The design you have will do a really great job at validating individual entities, but now you need to validate the rules for composing those entities into an event.