2012-02-24 26 views
5

Estoy leyendo el libro de Eric Evans sobre DDD y tengo una pregunta para la siguiente cita. ¿Cómo se hace su método equals() cuando no debe usar los atributos? Estoy usando JPA y tengo un atributo de identificación que es único, pero esto no se establece hasta que realmente persista la entidad. Entonces, ¿Qué haces? He implementado el método equals basado en los atributos y entiendo por qué no deberías hacerlo porque falló en mi proyecto.Entidades en el diseño impulsado por dominio

sección acerca de las entidades:

Cuando un objeto se distingue por su identidad, en lugar de sus atributos , hacen de esta primaria a su definición en el modelo. Mantenga la definición de clase simple y centrada en la continuidad del ciclo de vida y la identidad . Defina un medio para distinguir cada objeto independientemente de su forma o historial. Esté atento a los requisitos que requieren la coincidencia de objetos por atributos. Defina una operación que esté garantizada en y produzca un resultado único para cada objeto, posiblemente adjuntando un símbolo que sea único. Este medio de identificación puede venir del exterior, o puede ser un identificador arbitrario creado por y para el sistema, pero debe corresponder a las distinciones de identidad en el modelo. El modelo debe definir lo que significa ser lo mismo.

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

+0

duplicado Posible, ver http://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemma – MRalwasser

+0

El ello me da buenos resultados: http://stackoverflow.com/questions/7579404/using-auto-generated-id-of-hibenate-entity-object-in-the-equals-and-hashcode-met – NimChimpsky

Respuesta

1

Pareja enfoques posibles:

  • Utilice una clave de negocio. Este es el enfoque más "compatible con DDD". Mire de cerca los requisitos de dominio y negocios. ¿Cómo identifica su empresa a los clientes, por ejemplo? ¿Usan el número de seguridad social o el número de teléfono? ¿Cómo resolvería su empresa este problema si fuera en papel (sin computadoras)? Si no hay una clave comercial natural, cree un sustituto. Elija la clave comercial que sea definitiva y úselo en equals(). Hay una sección en el libro de DDD dedicada a este problema específico.

  • Para los casos en que no hay una clave comercial natural puede generar UUID. Esto también tendría una ventaja en el sistema distribuido, en cuyo caso no es necesario depender de recursos centralizados (y potencialmente no disponibles) como la base de datos para generar un nuevo ID.

  • También hay una opción para simplemente confiar en equals() predeterminado para las clases de entidad.Compararía dos ubicaciones de memoria y es suficiente en la mayoría de los casos porque Unit Of Work (Hibernate Session) se mantiene en todas las entidades (este patrón de ORM se llama Identity Map). Esto no es fiable, ya que se romperá si se utiliza entidades que no se limitan al ámbito de una sesión de Hibernate (hilos de reflexión, entidades separadas, etc.)

Curiosamente, 'oficial' de la muestra DDD utiliza un muy ligero marco en el que cada clase de entidad se deriva de Entity interfaz con un método:

boolean sameIdentityAs(T other) 
// Entities compare by identity, not by attributes. 
+0

Digamos que la entidad era la Pregunta. ¿Qué usaría? He confiado en la identificación generada hasta ahora. – LuckyLuke

+0

Depende de su dominio, tal vez el texto de la pregunta en sí (en cuyo caso tal vez sea Value not Entity), pero más probablemente algo así como el número de la pregunta. Realmente depende de tu dominio. – Dmitry

1

Si el objeto no es persistente, sin embargo, entonces hay ningún daño en la comparación de 2 objetos en función de sus atributos?

No estoy seguro de por qué esto falló en su proyecto, pero en mi experiencia, la comparación basada en atributos casi siempre es pendiente resbaladiza si sus atributos no son definitivos. Eso significa que 2 objetos que son iguales ahora pueden no ser iguales después de algún tiempo. Esto es muy malo.

Dado que la mayoría de las clases de Java se escriben junto con sus descriptores de acceso, equivale a decir que la comparación de atributos es una mala idea.

Sin embargo, probablemente verifique primero si el campo ID no es nulo. Si es nulo, me volvería a atribuir la comparación. Si no es nulo, solo úsalo y no hagas nada más. ¿Esto tiene sentido?

+2

Esto es algo peligroso de hacer. Si almacena el objeto en un HashSet antes de asignar su ID, el HashSet estará dañado. –

+0

Seguro. Pero, entonces, supongo que persistirías en el objeto para obtener la identificación. En cuyo caso, generalmente prefiero obtener el objeto persistente que se devuelve y usarlo. Básicamente, no mute el estado del objeto que se utiliza en la verificación de igualdad. – Pavan

+0

Si compara objetos en función de sus atributos, se está comportando como un objeto de valor, no como una entidad. Los objetos y las entidades de valor tienen una semántica bastante diferente en DDD, por lo que no debe basar la igualdad de la entidad en los atributos. –

1

Dada Person clase con atributos name, surname. Cuando Persona a la edad de 21 años cambia su nombre, ¿sigue siendo la misma Persona (es igual a true)? Si escribe igual en los atributos, no sería la misma persona, por lo que en mi opinión el mejor enfoque es probar la igualdad de entidades en su identificador de negocio (único e inmutable a lo largo de todo el ciclo de vida de la entidad).

0

Otra solución podría ser utilizar un campo UUID en su entidad.

En este caso, podría usar el UUID como clave principal o solo para iguales.

@Entity 
public class YourEntity{ 

    @Id 
    private String uuid = UUID.randomUUID().toString(); 

    // getter only... 

} 
Cuestiones relacionadas