Un desafío al utilizar hibernación es que las clases gestionadas deben tener un constructor predeterminado . El problema es que no hay un punto explícito en el que la clase se inicialice y se puedan verificar invariantes.Comprobar invariantes en las clases mapeadas de hibernación
Si una clase tiene invariantes que dependen de más de una propiedad, el diseño de clase se vuelve complejo. Vamos a empezar con el diseño hipotético-campo verde:
public class A {
private int x;
private int y;
public A(int x, int y) {
this.x = x;
this.y = y;
checkInvariants(this.x, this.y);
}
private void checkInvariants(int x, int y) {
if (x + y « 0) throw new IllegalArgumentException();
}
}
Esta es la implementación base que no cumpla con los requisitos de hibernación. El invariante se verifica en el constructor. (Método El contenido de los checkInvariants() No importa que sólo ha presentado para ilustrar que los invariantes de clase pueden depender más de una propiedad.)
La clase se puede utilizar de la siguiente manera:
new A(0, 0);
new A(-1, 0); //invalid
Para cumplir con los requisitos de hibernación una solución alternativa es agregar un constructor predeterminado privado y usar el acceso de campo. (I omitido las asignaciones de hibernación.)
public class H {
int x;
int y;
public H(int x, int y) {
this.x = x;
this.y = y;
checkInvariants(this.x, this.y);
}
H(){}
private void checkInvariants(int x, int y) {
if (x + y « 0) throw new IllegalArgumentException();
}
}
Esto tiene dos inconvenientes principales: * usted está comenzando a implementar el código que depende del cliente (Hibernate). Idealmente, una clase no conoce a sus llamadores. * Un problema específico con esta solución alternativa es que las instancias iniciadas por hibernación son no marcadas si cumplen con las invariantes. Confía en los datos que se cargan desde la base de datos que es problemático. Incluso si su aplicación es la única que usa este esquema de base de datos específico, siempre existe la posibilidad de cambios ad hoc por parte de los administradores.
Una segunda solución consiste en invariantes de verificación de código de usuario:
Obviamente, esto hace que el código de usuario más complejo y propenso a errores. Este diseño no cumple con la expectativa de que una instancia sea consistente después de la creación y se mantenga constante después de cada cambio de estado (llamada a método). Cada usuario tiene que verificar las invariantes para cada instancia que crea (tal vez indirectamente con hibernación).
¿Hay una mejor solución a este problema, que es:
- no excesivamente compleja
- sin conocimiento explícito sobre sus usuarios
- sin una dependencia con el marco de hibernación?
Supongo que algunas de las limitaciones deben aflojarse para llegar a una solución pragmática. La única restricción difícil es que no hay dependencia al marco de hibernación. (El código específico de Hibernate fuera de los objetos de dominio está bien).
(Solo por curiosidad: ¿hay un marco ORM que soporte la "inyección de constructor"?)
Este tipo de regla debería aplicarse mediante una restricción de comprobación en la base de datos, lo que evitaría que las instancias cargadas contravinieran la regla. – araqnid
La pregunta no es productiva. Está tratando de imponer una 'filosofía arbitraria' de aplicación de restricciones perpetuas a datos variables que, por definición, no son actualizables en una única actualización atómica. No está tratando de resolver un problema comercial o de diseño válido, simplemente empujando BS en un carro. –
@ThomasW Todos tienen un mal día de vez en cuando. ¡Aclamaciones! (Tal vez podría ayudar si descubres qué es un invariante). –