6

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.

dabadaba
  • 2,236
  • 1
    What's stopping you from passing e to the other validateStuff() methods? – Ixrec Apr 23 '16 at 17:57
  • the fact that I'd end up have 20+ methods with the same parameter validateX(Event e) which screams "extract me into a member variable!!" and 2. I can't do that anyway because the interface wouldn't cover that unless I make a class for each validable member, which is a crazy idea.
  • – dabadaba Apr 23 '16 at 18:00
  • 1
    Why you don't parametrize with Event all the other methods? Then all of them can be invoked from controller or from main validate method. I guess main validate method results is the sum off all others alltogether. Is'n it? – Laiv Apr 23 '16 at 18:14
  • Yes the sum of almost all others is what validate return, but I will also need them to be called individually from other classes. What do you mean with parametrize all other methods with Event? If it means the same than what what said in the first comment, I think I answered that in my comment above – dabadaba Apr 23 '16 at 18:17
  • 1
    Ok I see why you don't stack validation calls. But interface doesn't need to have 1 method per validation. Only its implementation has them all. Anyways if you are thinking in to have a single class with all the validations possibles, the coupling is going to be hard to avoid – Laiv Apr 23 '16 at 19:00
  • 1
    Given your choice of method names (validateCourts, validateMatches, etc.), it seems as if your individual objects should be validating themselves. What prevents you from saying something like public class Player implements Validator<Event>? – Robert Harvey Apr 23 '16 at 19:40
  • @RobertHarvey not at all. Those individual object must be validated in the context of the event. For example, that list of players is not null, that it contains more than 1 player or that the number of players it contains is a multiple of the defined number of players per match in the event, etc..... – dabadaba Apr 23 '16 at 19:42
  • 1
    Isn't that why you're passing an Event context? – Robert Harvey Apr 23 '16 at 19:42
  • @RobertHarvey yes of course that's the reason – dabadaba Apr 23 '16 at 19:43
  • Does the validation occur over the collection of players, and not the individual players? – Robert Harvey Apr 23 '16 at 19:43
  • @RobertHarvey Yes, it's over the collection. Although I might also need a validator for the player class, this is trivial, not important and the question does not regard this matter. – dabadaba Apr 23 '16 at 19:44
  • What does Event e contain? – Robert Harvey Apr 23 '16 at 19:45
  • @RobertHarvey a lot of members. If you really want to see... https://github.com/kpagcha/EventScheduler/blob/master/src/data/model/tournament/event/Event.java – dabadaba Apr 23 '16 at 19:46
  • I see Players and Timeslots in there, but not Courts or Matches. – Robert Harvey Apr 23 '16 at 19:48
  • @RobertHarvey It doesn't matter. I just made them up in the example to simplify what I meant. All you need to know is that "things should be able to be validated", what's so important about what these are? – dabadaba Apr 23 '16 at 19:49
  • So everything you need is in Event e then? You don't need to pull any data from anywhere else to do the validation? – Robert Harvey Apr 23 '16 at 19:50
  • @RobertHarvey nope, I don't. All I need is the event and the information it contains. It would be a closed scenario for validation. – dabadaba Apr 23 '16 at 19:51
  • And you don't need to add any outside behavior to Event e to cause the validation to happen? – Robert Harvey Apr 23 '16 at 19:51
  • @RobertHarvey that's a very abstract question, but the answer would be no. – dabadaba Apr 23 '16 at 19:53
  • Do you need multiple implementations of the validation, or just one? – Robert Harvey Apr 23 '16 at 19:53
  • @RobertHarvey for the moment just one but if it's not much of a fuss I would like to have an extensible design. – dabadaba Apr 23 '16 at 19:54
  • 1
    YAGNI. That said, it seems as if the design you have in your question is just fine. I'm not worried at all about the multiple methods that Laiv is worried about... those are all going to be internal to your validator. – Robert Harvey Apr 23 '16 at 19:54
  • @RobertHarvey As I said, I'm after extensibility. But if you really stand for YAGNI I would be more than happy to consider your suggestion if you can post it as an answer. According to you, what should be my implementation then? – dabadaba Apr 23 '16 at 19:55
  • 1
    Eh, it's just a suggestion, not a mandate. Everything is a tradeoff; there are no absolutes, even though programmers tend to think in terms of absolutes. If you do need multiple implementations later, it would seem that your Validator<Event> interface already provides that, so it would be quite straightforward to add that later. – Robert Harvey Apr 23 '16 at 19:57
  • 1
    The reason you need individual public method is because you need to call them separatelly from the code using the Event? Why is it not enough to call validate() and them check for messages? – Tulains Córdova Apr 23 '16 at 23:49
  • @TulainsCórdova basically the whole point of declaring individual validation methods is to avoid repeating code when checking preconditions and then postconditions (the object as a whole, when it's already supposed to be constructed). We could use pretty much the same individual validation "precondition" methods to valiadate the final state (postconditions) as most of them sumed up. – dabadaba Apr 24 '16 at 12:30
  • Comments are not for extended discussion; this conversation has been moved to chat. – yannis Apr 27 '16 at 23:52
  • @Yannis you are 4 days late, the conversation has ended, therefore there is no need of purposeless "modding" – dabadaba Apr 28 '16 at 08:27
  • Hm, you are right @dabadaba. The question had a pending "too many comments" flag, but I didn't notice it was days old when I cleared it. Usually we clear flags within 2-3 hours, no idea why this one stuck around for so long. – yannis Apr 28 '16 at 08:43