2010-09-13 13 views
5

Qual è il modo migliore per convalidare l'input? A titolo di argomento, se l'input non è valido, l'utente vorrebbe un messaggio che spieghi perché.Modello di progettazione per la convalida dell'input?

Ecco cosa posso inventare.

  • Validator metodo: Pass ingresso al validatore, che restituisce true se l'ingresso è valido. In caso contrario, il validatore restituisce false (o un codice di errore) e consente al chiamante di gestire l'input non valido. Oppure il validatore si assume la responsabilità di agire da solo. Oppure il validatore chiama un metodo di callback. Svantaggi: i passaggi adottati per la convalida potrebbero essere ripetuti quando viene chiamato il metodo effettivo.

  • Passare l'input direttamente al metodo, senza convalida. Lascia che il metodo gestisca i messaggi non validi. Può inviare direttamente il messaggio di errore all'utente o utilizzare un metodo di callback. Dopo aver inviato il messaggio, il metodo deve restituire o generare un'eccezione per interrompere l'elaborazione dell'input non valido. La classe chiamante continuerà alla riga successiva di input. Svantaggi: questo metodo ha ora un effetto collaterale dell'invio di un messaggio di errore.

Qual è la strategia appropriata qui? Si noti che non credo che il lancio di eccezioni sia appropriato perché la gestione dell'input non valido è una funzione principale dell'applicazione, almeno nel mio caso.

risposta

0

Forse guardate allo Command Pattern e inserite la logica di convalida nella classe invoker.

0

Non si deve passare l'input direttamente al metodo (suppongo che per "il metodo" intenda alcune logiche di business) per essere onesti in quanto accoppia la vista e il modello. Quello che dovresti fare è fare un controller con un metodo di validazione o una classe di validazione separata che prenda l'input e lo convalida usando alcuni metodi "esterni". Quindi, a seconda del risultato, il controller/validatore può restituire un errore di convalida o inoltrare l'input ovunque si desideri. Il più grande vantaggio di questo, come ho detto prima, è il disaccoppiamento del modello e della vista. Il modello non dovrebbe sapere nulla della vista (cosa succede se vuoi cambiare la vista? Dovrai riscrivere il tuo modello!). Non sono proprio sicuro del perché vorresti duplicare il codice di convalida nel modello di business? Validazione e navigazione dovrebbero essere ciò che fa un controller. Almeno è così che il pattern MVC fa qualcosa.
Anche lanciare eccezioni non è poi così male, ma dovrebbero essere lanciati nel modello e catturati nel controller. Ad esempio, si dispone di un sistema in cui si desidera che gli utenti dispongano di accessi unici, l'utente immetta un accesso già presente nel DB, il controllore chiama un metodo di convalida che tenta di (utilizzando il modello) di inserirlo nel DB. Se tutto va bene, viene inserito e il controller può restituire un messaggio "hai inserito un valore riuscito". Ma se il modello genera un'eccezione (come l'errore Unique Constraint Violation o qualcosa del genere), il controllore dovrebbe semplicemente prenderlo e restituire "questo accesso esiste già nel DB". In questo modo il modello non sa nulla della vista ed è riutilizzabile e non si ha la duplicazione del codice.

2

Dai un'occhiata al framework di validazione e validazione dei dati di Spring. Davvero molto bello e progettato per essere utilizzabile da solo o come parte di un'interfaccia utente.

+0

Nel caso in cui, le persone hanno bisogno di un link di riferimento https : //docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html – Eternalcode

0
public interface Validator { 
    /** 
    * Validates a JComponent</code>. 
    * @param component 
    *  The component to validate. 
    * @param message 
    *  The message to display if the validation fails. 
    * @return 
    *  Returns <code>false</code> if the validation fails, and 
    *  <code>true</code> otherwise. 
    */ 
    boolean validate(JComponent component, String message); 
} 

Si potrebbe avere un AbstractValidator (estende javax.swing.InputVerifier) ​​classe che fa gestisce la visualizzazione dei messaggi accanto al JComponent con una voce non valida.Date un'occhiata a this esempio

0

ora sto usando Hibernate quadro validatore, molto semplice e utile:

ho annotare le classi con quello che mi serve e poi lo uso:

La mia classe di entità:

public class Content { 

@NotNull 
private Heading heading; 

@NotNull 
@Length(max = 8) 
private String contentType; 

    // Everything else 

} 

mio Validator Component:

@Component 
public class Validator implements IValidator { 
    protected static Log log = LogFactory.getLog(Validator.class); 

    javax.validation.Validator validator; 

    @Autowired 
    WebApplicationExceptionBuilder webApplicationExceptionBuilder; 

    public void validate (Object entity) throws WebApplicationException { 
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
     validator = factory.getValidator(); 
     Set<ConstraintViolation<Object>> violations = validator.validate(entity); 
     if (!violations.isEmpty()) { 
      webApplicationExceptionBuilder 
         .raise("some fields are missing or incorrect", 
          violations); 
     } 
    } 

} 

Dove usarlo:

public class Foo{ 

    @Autowired 
    private IValidator validator; 

    @Autowired 
    private IContentService contentService; 

    public void bar(Content c) throws Exception{ 
     validator.validate(c); 
     contentService.persist(content); 
    } 

} 
1

una bella soluzione per la convalida gli oggetti senza l'onere di creare molte classi che implementano un'interfaccia "validatore" o utilizzando classi interne anonime che non sono riutilizzabili, è utilizzare la funzionalità costante di un'enumerazione:

Nell'esempio:

public enum ObjectValidation { 

BAD_DATE_FORMAT(ErrorCode.BAD_DATE_FORMAT) { 

    @Override 
    boolean validate(String value, List<String> acceptableValues) { 
     boolean isValid = false; 
     // validate the date 
     SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 
     try { 
      sdf.parse(value); 
      isValid = true; 
     } catch (ParseException ex) { 

     } 

     /* 
     * We could use acceptableValues to validate the value against a 
     * list of acceptable values 
     */ 

     return isValid; 
    } 

}; 

private ErrorCode errorCode; 

private ObjectValidation(ErrorCode ErrorCode) { 
    this.errorCode = ErrorCode; 
} 

public ErrorCode getErrorCode() { 
    return errorCode; 
} 

abstract boolean validate(String value, List<String> acceptableValues); 

}

E il metodo di servizio che sfruttano la funzionalità di convalida costante fornita dal enum e può essere utilizzato per più convalide dello stesso campo:

public static List<ErrorCode> validate(String value, Set<ObjectValidation> objectValidators) throws Exception{ 
     List<ErrorCode> errorCodeList = new ArrayList<ErrorCode>();   
     for (ObjectValidation objectValidation : objectValidators) { 
      if(!objectValidation.validate(value, Collections.emptyList())){ 
       errorCodeList.add(objectValidation.getErrorCode()); 
      } 
     }    
    return errorCodeList;  
} 
Problemi correlati