Progettazione di classi di validazione

5

Questo è un follow-up di questa domanda . Ho deciso di implementare ciò che la risposta accettata suggerisce, tuttavia, mi sono reso conto che avevo bisogno anche di metodi pubblici individuali per ogni membro che l'entità da convalidare ha, quindi non è solo convalidato nel suo insieme, ma anche i suoi membri come unità separate:

Questo è ciò che è stato suggerito:

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...
}

Ma ora ho bisogno di metodi pubblici per ogni membro di Event . Il motivo è utilizzare ognuno di questi metodi in Event setter e metodi con uno scopo simile, come aggiungere elementi a un elenco o a un dizionario, inizializzare i dati, modificare i dati, ecc.

Quindi mi servirebbe qualcosa come:

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

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

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

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

Questa prima cosa che posso vedere è che devi convertire il parametro Event e nel metodo "main" validate(Event e) in una variabile membro in modo che il resto dei metodi possa accedervi. Ma questo viola l'intero punto di questo progetto, che stava separando l'entità dal validatore.

Quale sarebbe il design più adatto a coprire le mie esigenze? Non mi interesserebbe se dovessi ricominciare da zero e dimenticare completamente il design attuale.

    
posta dabadaba 23.04.2016 - 19:49
fonte

3 risposte

1

Penso che potrebbe aiutare a capire che Validable e Validator sono interfacce che si riferiscono alla validazione di una singola entità e che ora stai cercando di forzare la convalida di un composito di entità in questo progetto. Il tuo Validator dovrebbe solo validare l'evento, non provare a usarlo per convalidare le regole per la creazione dell'evento. Fai una distinzione tra l'evento e le regole per la creazione dell'evento .

Una volta ottenuto questo approfondimento, hai molte opzioni in futuro.

Sembra che tu stia modellando una partita di tennis. In tal caso, un evento dovrebbe probabilmente essere creato da qualche tipo di match-maker. (Potrebbe essere adatto a utilizzare il modello di build?) Ciò che in realtà si desidera convalidare non è l'evento , ma i passaggi nel processo di creare un evento . Il design che hai farà un ottimo lavoro nel convalidare le singole entità, ma ora devi convalidare le regole per comporre quelle entità in un evento.

    
risposta data 24.05.2016 - 14:47
fonte
0
public class EventValidator implements Validator<Event> { 
    // Validates the whole object 
        public boolean validate(Event e){ 
           return validatePlayers(e) && 
    validateCourts(e) && 
    validateMatches(e);
          // and so on....
        } 
        public boolean validatePlayers(Event e) {
            event.getPlayers() ...
            // ... 
        }
        public boolean validateCourts(Event e) { 
            event.getCourts() ...
             // ... 
        } 
        public boolean validateMatches(Event e) { 
            // ... 
         }
 }

Questo è quello che stavo suggerendo nel mio commento. Con tutti gli altri pubblici, possono essere invocati singolarmente per validazioni singolari. Inoltre, il metodo principale è il risultato di tutti gli altri. (O qualsiasi altra logica di validazione).

Chi ti ha suggerito questa strategia è stata davvero intelligente. La strategia sotto è la stessa sotto l'interfaccia Comparatore . Non ti preoccupare per questo accoppiamento. È davvero un accoppiamento morbido.

Se non vuoi avere alcun tipo di accoppiamento, devi usare un tipo personalizzato come parametro invece di Event. Diciamo Validabile

Validabile è un'interfaccia che deve essere implementata da qualsiasi entità del candidato al codice da convalidare.

Questa interfaccia ha anche 1 metodo isValid () . E ogni classe che implementa questa interfaccia ha il compito di convalidare se stessa. EventValidator attiva solo una catena di esecuzione isValid () .

Ma questo approccio richiede un piccolo rifrattore. Lo pubblicherei ma ci vorrebbero anni per farlo dal mio smartphone.

Spero che questo ti aiuti.

.-.-.-.-.-

Nota : se hai così tante convalide, in effetti, avere 20 metodi è una progettazione piuttosto scadente. Quindi la tua scelta è: avere 20 validatori. Questo potrebbe sembrare troppo codice, ma è preferibile che 20 classi facciano semplici azioni su una semplice classe facendo 20 cose diverse. La mia classe fa solo 1 cosa, ma funziona bene . Per fare in modo che X Validator ti permetta di riutilizzare un codice così piccolo in qualsiasi punto del progetto. Inoltre è aperto a possibili convalide composte (per composizione o ereditarietà)

    
risposta data 23.04.2016 - 20:42
fonte
0

Questa è una progettazione alternativa in cui più convalide "step" possono essere chiamate separatelly:

== > IValidable.java < ==

import java.util.List;

public interface IValidable {
    public void setValidator(IValidator<Event> validator_);
    public void validate(String stepTag) throws ValidationException, UnknownStepTagException;
    public String getLastValidationMessage();
}

== > IValidator.java < ==

import java.util.List;

public interface IValidator<T> {
    public boolean validate(T e, String stepTag) throws UnknownStepTagException;
    public String getLastValidationMessage();
    public String getLastStepTag();
}

== > Event.java < ==

import java.util.List;

public class Event implements IValidable {

    public static final String VALIDABLE_STEP_PLAYERS="PLAYERS";
    public static final String VALIDABLE_STEP_COURTS="COURTS";
    public static final String VALIDABLE_STEP_MATCHES="MATCHES";

    private IValidator<Event> validator;
    private String lastValidationMessage;

    @Override
    public void setValidator(IValidator<Event> validator_) {
        this.validator = validator_;
    }

    @Override
    public void validate(String stepTag) throws ValidationException, UnknownStepTagException {
        if (!this.validator.validate(this,stepTag)){
            throw new ValidationException("WTF!");
        }
    }

    @Override
    public String getLastValidationMessage() {
        return this.lastValidationMessage;
    }

}

== > SimpleEventValidator.java < ==

public class SimpleEventValidator implements IValidator<Event> {

    private String lastValidationMessage ="";
    private String lastStepTag="";
    @Override
    public boolean validate(Event e, String stepTag) throws UnknownStepTagException {
        // based on the stepTag executed appropiate privateMethod
        // this example always returns false    
        this.lastStepTag=stepTag;
        return false;
    }

    @Override
    public String getLastValidationMessage() {
        return this.lastValidationMessage;
    }

    @Override
    public String getLastStepTag() {
        return this.lastStepTag;
    }

    private boolean validateThis(){
        return false;
    }

    private boolean validateThat(){
        return false;
    }       

}

== > UnknownStepTagException.java < ==

public class UnknownStepTagException extends Exception {

}

== > ValidationException.java < ==

public class ValidationException extends Exception {
    public ValidationException(String message) {
        super(message);
    }

    private static final long serialVersionUID = 1L;
}

== > Test.java < ==

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main (String args[]){
        Event e = new Event();
        IValidator<Event> v = new SimpleEventValidator();
        e.setValidator(v);
        List<String> messages = new ArrayList<String>();
        // set other thins to e like
        // e.setPlayers(player1,player2,player3)
        // e.setNumberOfMatches(3);
        // etc
        try {
            e.validate(Event.VALIDABLE_STEP_COURTS);
            messages.add(e.getLastValidationMessage());
            e.validate(Event.VALIDABLE_STEP_MATCHES);
            messages.add(e.getLastValidationMessage());
            e.validate(Event.VALIDABLE_STEP_PLAYERS);
            messages.add(e.getLastValidationMessage());
        } catch (ValidationException e1) {
            messages.add(e.getLastValidationMessage());
            System.out.println("Your event doesn't comply with the fedaration regulations for the following reasons: ");
            for (String s:messages){
                System.out.println(s);
            }
        } catch (UnknownStepTagException e2) {
            System.out.println("Unknown validation step "+v.getLastStepTag());
        }
    }
}

===============

    
risposta data 22.08.2016 - 20:07
fonte

Leggi altre domande sui tag