Pregunta

Tengo una clase: agenda

.
public class Schedule {

private int locationNum;
private int cost;
private String costReason; 
private Date weekOfChange;
private Date dayOfChange;
private String changeReason; 

// and all those getters and setters

public Schedule(int locationNum, int cost, String costReason, Date weekOfChange, Date dayOfChange, String changeReason) throws ApplicationException {
//change is all or nothing - all attributes are present or none
if((weekOfChange!=null && dayOfChange!=null && changeReason!=null) || (weekOfChange==null  && dayOfChange == null && changeReason == null))  {
this.weekOfChange = weekOfChange;
this.dayOfChange = dayOfChange;
this.changeReason = changeReason;
}
else { throw new ApplicationException();}
//similary another if block to ensure that if cost is specified 
//then there exists the corresponding reason code for it.
}
}

Hasta el momento, estoy gustando mi clase de programación. Sin embargo, no he terminado con los controles, que tendría que hacer algunas otras comprobaciones:

  • es el locationNum un número de tienda válido en la base de datos.
  • es changeReason texto uno de los 6 diferentes códigos changeReason en la base de datos.
  • , etc, etc ....

Por lo general, no escribiría esto en la clase de programación, coz, obviamente, no puedo invocar DAOs de esta clase. Por lo tanto, me gustaría tener una capa de negocio y algún tipo de clase de validador, aceptando un objeto de tipo Planificar y llevar a cabo un montón de validaciones de bases de datos en secuencia y la recogida de errores para la visualización / lo que sea.
Ahora, aquí están mis preguntas:

  1. Si se va a tratar la Lista como un POJO y argumentar que un objeto no es responsable de validar sí mismo - que tendría que mover todo el código en el constructor de clase de validador de la capa de negocio. Sin embargo, si tuviera que hacer esto, no es la Lista anémica? Es esto lo que llaman violación del principio de responsabilidad única?
  2. Permite presumo moví el código que tengo en mi constructor para una clase de capa de negocio para que todo tipo de validaciones están ahora en mi capa busines. Asumamos que alguien cambia dayOfChange a NULL en mi almacén de datos y ahora estoy cargando los objetos de mi base de datos. Ahora, con este tipo de un objeto, mi solicitud puede romper, ¿verdad? coz que habría escrito el código siempre que se cumplan las reglas de validación. Creo que mi pregunta es cada vez confuso, pero el punto que estoy tratando de hacer es que, en este contexto, yo preferiría tener estas comprobaciones realizadas en el constructor para asegurar la integridad de los datos ocultos por clase Horario.
  3. ¿Cómo se realiza por lo general? ¿Cuál es la mejor práctica?

Agradecemos su participación en esta discusión.

¿Fue útil?

Solución

Si realmente tiene "todos los métodos get y set", entonces usted necesita para validar su clase mejor que en el constructor. Si los invariantes de su clase son tales que todos weekOfChange, dayOfChange y changeReason debe ser nulo o no todos deben ser no nulo sus emisores están pasando rápidamente a poner su clase en un estado no válido. ¿Quiere decir que tiene fijadores o qué significa la clase de ser inmutable?

Antes de preocuparse por fuera de validación debe ir tal vez hacer un análisis de su clase. Mira todos sus estados e invariantes válidas para determinados estados. Entonces comprenderás si su clase debe ser mutable o inmutable. Donde tiene covariantes mutuamente dependientes (como weekOfChange, dayOfChannge y changeReason que tiene sentido para empaquetarlos en existencia propia clase y el uso de la composición de la clase de programación. Esto hará que las "reglas" sobre estos campos las cosas en un solo lugar y simplificar la Lista .

Lo mismo con otros campos colaboradoras (como el costo y la razón de costos). Luego de programación se compone de clases de auto validación. Si ambos son inmutables y horario es inmutable también tiene a su auto un dominio mucho más fácil.

Por lo tanto, para responder a su pregunta: ¿es mejor que una clase define sus estados e invariantes y expone sólo el mínimo a sus colaboradores cuando sea práctico. La responsabilidad por el estado interno de la Lista debe recaer en la Lista y con sólo un poco más de diseño que puede hacer con relativa facilidad.

Por lo que tiene

    class Schedule {
         private Change change;
         private Cost cost;
         private Location location;

        public Schedule(Location location, Cost cost, Change change) {
           this.change = change;
           this.cost = cost;
           this.location = location;
        }
}

Y como colloborators

public class Change {
    private Date weekOfChange; //shoudln't these two fields be one, a date is a date after all??
    private Date dayOfChange; //shoudln't these two fields be one??
    private String changeReason; 

    public Change(Date weekOfChange Date dayOfChange, String changeReason) {
      this.weekOfChange = weekOfChange;
      ...etc.
    } 
}

A pesar de que les recomiendo vivamente a proteger sus clases invariantes con el copiado defensiva de los valores mutables que se pasan por el código de cliente.

Otros consejos

  

Si se va a tratar la Lista como una   POJO y argumentan que un objeto no es   encargado de validar sí - me   tendría que mover todo el código de   el constructor para el negocio   clase de validador de capa. Pero si yo   fueron a hacer esto, no es la Lista   ¿anémico? Es esto lo que llaman   violación de la responsabilidad individual   principio?

POJO sólo significa que usted no tiene que derivar de una clase o de uso particular un promotor de código de bytes para obtener la funcionalidad similares o mapeo se desea. No significa que los objetos deben ser anémicos sin funcionalidad.

  

Ahora, con este tipo de un objeto, mi   aplicación puede romper, ¿verdad?   coz que tendría código escrito asumiendo   que se cumplan las reglas de validación. supongo   mi pregunta es cada vez confuso, pero   el punto que estoy tratando de hacer es que   En este contexto, yo preferiría tener   estas comprobaciones hechas en constructor para   asegurar la integridad de los datos ocultos por   Horario de clases.

¿Quién dice que no se puede llamar reglas definidas en una clase separada desde el constructor de la clase Horario? Si necesita tener acceso a campos que no son públicas, se puede hacer que se empaquetan-privada y tener la clase de reglas en el mismo paquete -. O pasarlos como parámetros a la regla

  

¿Cómo se hace por lo general? Cuál es el   las mejores prácticas?

Si o no se mueve reglas de validación a clases separadas deben depender de las necesidades de su aplicación, no en palabras de moda mal entendidas.

Buena razones para tener clases de reglas separadas sería:

  • Las reglas son tantos y tan complejos que poner a todos en la clase Horario haría demasiado grande.
  • Usted no siempre se desea aplicar todas las reglas.
  • Las reglas puede ser reutilizado para operar en diferentes clases que no son necesariamente en la jerarquía misma herencia (es decir, que trabajan a través de una interfaz).

Parece que hay dos comportamientos distintos para el constructor Schedule. Hay, por lo tanto, debe ser dos constructores. Posiblemente incluso dos clases de implementación.

locationNum y changeReason. Estos son actualmente tipos débiles. Que probablemente debería tener su propia clase. Después de su pregunta, los valores válidos dependen del contexto. Por el momento Schedule no tiene ningún contexto. Se podría mantener Schedule independiente del contexto, en cuyo caso no hay limitaciones de bases de datos sobre locationNum y changeReason. Siguiendo el camino de otro, Schedule, locationNum y changeReason podría ser dependiente del contexto, y el constructor simplemente debe comprobar que todos están en el mismo contexto. Un constructor paquete-privada (que actúa como friend de un hombre pobre) podrá omitir los controles.

Un POJO implica un objeto (bien escrito) y por lo tanto el comportamiento. La pregunta parece estar usando que signifique "estructura". Evitar estructuras.

Capa de negocio parece ser engañosa. Parece ser una entidad comercial, que debe tener un comportamiento empresarial. Sin embargo, no puede contener de procesos de negocio (servicio).

Su aplicación siempre asumirá ciertas cosas sobre la base de datos, incluyendo el esquema (público). Si elimina las limitaciones, a continuación, que bien puede romper su aplicación. Esto es lo mismo que si de manera similar código que se dependía cambiado.

La práctica común es tener objetos anémicos con el código de procedimiento. Para la mayoría de los casos, esto no es la mejor práctica.

¿Por qué es un int locationNum cuando en realidad se hace referencia a una instancia de otra clase, por ejemplo la ubicación? Si desea utilizar referencias a objetos adecuados que podría validarlos en la Lista y configurar el ORM (si lo hay) para hacer cumplir la integridad referencial.

para responder a sus preguntas:

1) No creo que la clase será anémica, que será más bien un DTO, por el momento, no veo ningún problema con esto.

2) Si la validación no es en la capa de negocio, esto no significa que voy a recibir un objeto no válido, ya que la validación todavía estará allí, normalmente el proceso de validación de alguna manera se quejan de un InvalidDataException o algo y won 't le permiten usar el objeto 'corrupto'. Si la fecha nula no es un valor aceptable (nulo normalmente no podría entrar en la base de datos), entonces la capa de negocio / DAO debe coger este error y evitar que el objeto se acostumbre por su aplicación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top