2010-09-13 15 views
5

¿Cuál es la mejor manera de validar la entrada? Por razones de argumento, si la entrada no es válida, el usuario desea un mensaje que explique por qué.¿Patrón de diseño para validar la entrada?

Esto es lo que se me ocurre.

  • Validator método: Pase de entrada al validador, que devuelve true si la entrada es válida. De lo contrario, el validador devuelve false (o un código de error) y permite que la persona que llama maneje la entrada no válida. O el validador asume la responsabilidad de actuar por sí mismo. O el validador llama a un método de devolución de llamada. Inconvenientes: los pasos para validar se pueden repetir cuando se llama al método real.

  • Pase la entrada directamente al método, sin validación. Deje que el método maneje los mensajes no válidos. Puede enviar el mensaje de error directamente al usuario o usar un método de devolución de llamada. Después de enviar el mensaje, el método debe devolver o lanzar una excepción para detener el procesamiento de la entrada no válida. La clase de llamada continuará a la siguiente línea de entrada. Inconvenientes: este método ahora tiene un efecto secundario al enviar un mensaje de error.

¿Cuál es la estrategia adecuada aquí? Tenga en cuenta que no creo que arrojar excepciones es apropiado porque el manejo de entradas no válidas es una función central de la aplicación, al menos en mi caso.

Respuesta

0

Quizás mire en Command Pattern y ponga la lógica de validación en la clase de invocador.

0

No debe pasar la entrada directamente al método (supongo que por "el método" significa alguna lógica de negocios) para ser honesto, ya que combina la vista y el modelo. Lo que debe hacer es crear un controlador con un método de validación o una clase de validación separada que tome la entrada y valide utilizando algunos métodos "externos". Luego, dependiendo del resultado, el controlador/validador puede devolver un error de validación o reenviar la entrada donde desee. El mayor beneficio de esto, como dije antes, es el desacoplamiento del modelo y la vista. El modelo no debería saber realmente nada sobre la vista (¿y si quiere cambiar la vista? ¡Tendrá que volver a escribir su modelo!). No estoy muy seguro de por qué quieres duplicar el código de validación en el modelo de negocio? La validación y la navegación deberían ser lo que hace un controlador. Al menos así es como el patrón MVC hace las cosas.
También lanzar excepciones no es tan malo, pero deberían arrojarse en el modelo y quedar atrapados en el controlador. Por ejemplo, tiene un sistema donde desea que los usuarios tengan inicios de sesión únicos, el usuario ingresa un inicio de sesión que ya está en la base de datos, el controlador llama a un método de validación que intenta (utilizando el modelo) insertarlo en la base de datos. Si todo va bien, entonces se inserta y el controlador puede devolver el mensaje "insertó un valor exitoso". Pero si el modelo arroja una excepción (como el error de Violación de Restricción Única o algo así), entonces el controlador simplemente debe atraparlo y devolver "este inicio de sesión ya existe en el DB". De esta forma, el modelo no sabe nada sobre la vista y es reutilizable y no tiene duplicación de código.

2

Eche un vistazo a la estructura de validación y atascamiento de datos de Spring. Muy bonito, y diseñado para ser utilizado solo o como parte de una interfaz de usuario.

+0

En el caso, la gente necesita un enlace de referencia 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); 
} 

Usted podría tener un AbstractValidator (Extiende javax.swing.InputVerifier) ​​clase que se encarga de pantalla de mensajes junto a la JComponent con una entrada no válida.Echar un vistazo a this ejemplo

0

ahora estoy utilizando el framework de validación de hibernación, muy simple y útil:

anoto clases con lo que necesito y luego usarlo:

Mi clase de entidad:

public class Content { 

@NotNull 
private Heading heading; 

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

    // Everything else 

} 

Mi Validador de componentes:

@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); 
     } 
    } 

} 

Dónde utilizarlo:

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 buena solución para la validación de los objetos sin la carga de la creación de muchas clases que implementan una interfaz "validador" o el uso de clases internas anónimas que no son reutilizables, es utilizar la funcionalidad constante de una enumeración:

En el ejemplo:

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); 

}

Y el método de servicio que aprovechan la funcionalidad de validación constante proporcionada por la enumeración y se puede utilizar para múltiples validaciones del mismo 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;  
}