2011-01-16 11 views
13

Analizamos detenidamente nuestros patrones de aplicaciones web (Java). En el pasado, sufrimos de un modelo de objetos excesivamente anémico y de una separación excesivamente de procedimientos entre los controladores, los servicios y los DAO, con objetos de valor simple (básicamente solo bolsas de datos) que viajaban entre ellos. Hemos utilizado el ORM (Hibernate) gestionado declarativo (XML) para la persistencia. Toda la gestión de la entidad se ha llevado a cabo en DAO.DDD: dónde ubicar la lógica de persistencia y cuándo usar la asignación de ORM

Al tratar de pasar a un modelo de dominio más completo, nos encontramos luchando con la mejor manera de diseñar la capa de persistencia. Pasé mucho tiempo leyendo y pensando en los patrones de diseño impulsados ​​por el dominio. Sin embargo, me gustaría un consejo.

En primer lugar, las cosas que estoy más seguro de:

  • tendremos controladores "finas" en la parte delantera que se ocupan solamente de HTTP y HTML - formas de procesamiento, validación, la lógica de interfaz de usuario.

  • Tendremos una capa de servicios lógicos de negocios sin estado que implementa algoritmos comunes o lógica, desconoce la interfaz de usuario, pero muy consciente de (y delegando) el modelo de dominio.

  • Tendremos un modelo de dominio más completo que contiene estado, relaciones y lógica inherente a los objetos en ese modelo de dominio.

La pregunta se trata de la persistencia. Anteriormente, nuestros servicios se inyectarían (a través de Spring) con DAO y utilizarían métodos DAO como find() y save() para realizar la persistencia. Sin embargo, un modelo de dominio más rico parecería implicar que los objetos deberían saber cómo guardarse y eliminarse, y tal vez que los servicios de nivel superior deberían saber cómo ubicar (consultar) los objetos de dominio.

Aquí, algunas preguntas e incertidumbres surgen:

  • es lo que queremos para inyectar DAOs en objetos de dominio, por lo que pueden hacer "this.someDao.save (esto)" en un save() ¿método? Esto es un poco incómodo ya que los objetos de dominio no son únicos, por lo que necesitaremos fábricas o configuraciones de DAO posteriores a la construcción. Al cargar entidades desde una base de datos, esto se complica. Sé que Spring AOP se puede usar para esto, pero no pude hacerlo funcionar (usando Play! Framework, otra línea de experimentación) y parece bastante desordenado y mágico.

  • ¿En lugar de eso, mantenemos los DAO (repositorios) completamente separados, a la par de los servicios lógicos de negocios sin estado? Esto puede tener algún sentido, pero significa que si "guardar" o "eliminar" son operaciones inherentes de un objeto de dominio, el objeto de dominio no puede expresarlas.

  • ¿Acabamos de prescindir por completo de los DAO y utilizamos JPA para que las entidades puedan administrarse solos?

Aquí radica la siguiente sutileza: es bastante conveniente mapear entidades usando JPA. ¡El juego! framework nos da una buena clase base de entidad, también, con operaciones como save() y delete(). Sin embargo, esto significa que las entidades de nuestros modelos de dominio están estrechamente vinculadas a la estructura de la base de datos, y estamos pasando objetos con una gran cantidad de lógica de persistencia, tal vez hasta la capa de vista. Si nada más, esto hará que el modelo de dominio sea menos reutilizable en otros contextos.

Si queremos evitar esto, entonces necesitaríamos algún tipo de asignación DAO, ya sea usando JDBC simple (o al menos Spring's JdbcTemplate), o usando una jerarquía paralela de entidades de base de datos y entidades "comerciales", con DAOs siempre copiando información de una jerarquía a otra.

¿Cuál es la opción de diseño adecuada aquí?

Martin

+3

De acuerdo con el diseño impulsado por el dominio - los objetos de dominio deben ser persistentes ignorantes. –

Respuesta

1

No soy un experto en Java, pero yo uso NHibernate en mi código .NET así que mi experiencia debe ser directamente traducible al mundo Java.

Al usar ORM (como Hibernate que usted mencionó) para construir la aplicación de Diseño Dirigido por Dominio, una de las mejores prácticas (no diré mejor) es crear los llamados servicios de aplicación entre la UI y el Dominio. Son similares a los objetos comerciales sin estado que mencionaste, pero no deberían contener casi ninguna lógica. Se debe tener este aspecto:

public void SayHello(int id, String helloString) 
{ 
    SomeDomainObject target = domainObjectRepository.findById(id); //This uses Hibernate to load the object. 

    target.sayHello(helloString); //There is a single domain object method invocation per application service method. 

    domainObjectRepository.Save(target); //This one is optional. Hibernate should already know that this object needs saving because it tracks changes. 
} 

Cualquier cambio a los objetos contenidos por DomainObject (también añadir objetos a las colecciones) estará a cargo de hibernación.

También necesitará algún tipo de AOP para interceptar las invocaciones del método de servicio de la aplicación y crear la sesión de Hibernate antes de que el método se ejecute y guardar los cambios después de que el método finalice sin excepciones.

Hay una muy buena muestra de cómo hacer DDD en Java here. Se basa en el problema de muestra de Eric Evans ''Blue Book'. El código de muestra de clase de lógica de aplicación es here.

3

Sus preguntas y dudas suenan una alarma interesante aquí, creo que fue demasiado lejos en su interpretación de un "modelo de dominio enriquecido". La riqueza no llega a implicar que los objetos de dominio deben manejar la lógica de persistencia; en otras palabras, no, no deberían saber cómo guardarse y eliminarse (al menos no explícitamente, aunque Hibernate en realidad agrega cierta lógica de persistencia) transparentemente). Esto a menudo se conoce como ignorancia de persistencia.

Le sugiero que guarde el sistema de inyección DAO existente (algo bueno para pruebas unitarias) y abandone la capa de persistencia mientras intenta mover alguna lógica comercial a sus entidades donde encaja. Un buen punto de partida para hacerlo es identificar Agregados y establecer sus Raíces agregadas. A menudo contendrán más lógica comercial que las otras entidades.

Sin embargo, esto no quiere decir que los objetos de dominio contengan todos lógica (especialmente no lógica necesaria para muchos otros objetos en la aplicación, que a menudo pertenece a Servicios).

+0

Bueno, punto justo. Pero mira la última parte de mi pregunta: algo como Hibernate/JPA hace que sea mucho más fácil lidiar con la persistencia. Sin embargo, si hacemos esto en el modelo de dominio, entonces tiene esta lógica incorporada. Si no lo hacemos, entonces tendremos que renunciar a ORM por completo, o tener una jerarquía paralela de objetos "mapeados" y "dominio" objetos y mapeadores de datos entre ellos. – optilude

+0

El uso de JPA no significa que los objetos de dominio deben persistir por sí solos: solo contienen descripciones de cómo asignarse a las tablas de la base de datos, y en este aspecto JPA es menos persistente e ignorante en comparación con Hibernate puro. – guillaume31

+0

Así que no recomiendo inyectar DAO en objetos de dominio. En JPA y DDD puede encontrar estas 2 publicaciones de blog interesantes: http: //debasishg.blogspot.com/2007/10/domain-modeling-with-jpa-gotchas-part-4.html http://debasishg.blogspot.com/2007/10//domain-modeling-what-excaly-is-rich.html Tampoco iría a la "jerarquía paralela" ya que presenta una complejidad innecesaria en comparación con solo POJO. – guillaume31

Cuestiones relacionadas