java - ¿Las anotaciones de persistencia en objetos de dominio son una mala práctica?
hibernate annotations (7)
Creo que usaré anotaciones en mi dominio si ya estoy decidido con el marco de persistencia que voy a usar, sin embargo, XML sería más conveniente si sigues la arquitectura Hexagonal y TDD. Si realiza una anotación en su dominio con un marco de trabajo específico por adelantado, se le unirá a la integración de persistencia y no podrá probar la funcionalidad principal con el objetivo de ser independiente de la tecnología / marco.
Me doy cuenta de que los marcos de persistencia como Morphia e Hibernate se basan en anotaciones en objetos de dominio para hacer su magia. A cierto nivel, me parece que esto es insertar preocupaciones de persistencia en la capa de dominio, que es algo que debemos esforzarnos por evitar.
¿Es esto algo que debería tratar de esquivar utilizando quizás un archivo de configuración externo o quizás DTO separados del modelo de dominio? ¿O es esta pequeña fuga entre la persistencia y las capas de dominio generalmente considerada como aceptable?
En mi última iteración en un sistema existente que usa Spring e Hibernate, comencé a moverme en un asunto similar. Cuando implementé los modelos de Hibernate por primera vez, intenté separar la lógica de la aplicación en las clases de servicio de la lógica de persistencia a través de los objetos de acceso a datos. Cuando construí un nuevo sistema el año pasado, permití que la mayoría de los objetos de persistencia sirvieran como objetos de dominio porque esa era la solución conveniente.
Sin embargo, estoy rediseñando este mismo sistema a la luz de los cambiantes requisitos comerciales, y me inclino nuevamente por separar esas preocupaciones. Solo llevo unos pocos días en el nuevo diseño, pero ya me encuentro prefiriendo tener un objeto que represente al objeto de preocupación en memoria mientras que un objeto separado basado en la persistencia se usa para almacenar los cambios de estado en la base de datos. Por ejemplo, tengo un Lead
para la persistencia y un ActiveLead
paralelo que vive en las transacciones.
Todavía no estoy convencido de que este sea el mejor método, pero tiene sentido en un nivel mínimo. He anhelado tener una colección de objetos que permanezcan en la memoria a través de las bases de datos sin importar las simplificaciones estándar de CRUD. Sin embargo, entiendo que al final todas las operaciones de base de datos se implementan como CRUD. Los dos mundos deben chocar, y el truco está en hacer que bailen en armonía.
Hibernar anotaciones en objetos de dominio? Este es un buen compromiso entre la facilidad de implementación y la facilidad de mantenimiento en mi opinión.
En mi opinión, no es necesario duplicar los objetos del dominio para poder separarlos de la capa de persistencia. Funciona duplicando el código en la mano y es perfectamente factible utilizando los mismos objetos que los DTO. Si es necesario, siempre puede usar clases separadas si es necesario, pero no lo haría una regla general, le costará tiempo y todos sabemos que el tiempo es valioso.
Preferiría objetos de dominio ricos que tengan las anotaciones en él. Incluso Evans utiliza este enfoque en su aplicación de muestra . Utiliza XMl en lugar de anotaciones, pero aún persiste los mismos objetos.
Tal vez sea más limpio separar el dominio y la persistencia, pero no lo haga solo para poder elegir potencialmente una tecnología de db diferente en el futuro. Es el camino a la complejidad del infierno y Mister YAGNI te morderá.
Recientemente he trabajado en un sistema razonablemente complejo con una capa de persistencia separada, y fue un gran dolor en el culo y muy malo para el mantenimiento. Básicamente, estás viendo un conflicto entre los principios de YAGNI y la responsabilidad única. En mi opinión, YAGNI es el más importante (por desgracia, también el que se ignora con más frecuencia).
Diría que en la gran mayoría de los casos, es mucho mejor persistir en los objetos de dominio directamente si está utilizando un ORM, a menos que tenga requisitos concretos que obliguen a las entidades de persistencia a estructurarse de manera diferente (si tienen exactamente la misma estructura, no hay razón para separarlos excepto los argumentos de la torre de marfil).
Para estar seguro: ¡ siempre haga las cosas de persistencia reales (llamadas funciones ORM) en una capa de servicio / DAO separada! De esa manera, es fácil introducir una capa de persistencia más adelante si encuentra que la necesita.
Respuesta corta: Me gustan los objetos de dominio, persistentes y ricos.
Respuesta larga:
Durante casi 10 años trabajé en un sistema bastante grande ~ 500k LOC usando Spring e Hibernate. Al principio, comenzamos con un enfoque de "script de transacción" (ver Fowler), en parte porque no confiábamos en Hibernate. Sin embargo, en poco tiempo, llegamos a confiar en Hibernate y debido a mi entrenamiento más temprano en OO bastante purista, me convertí en un gran creyente en la persistencia transitoria combinada con un enfoque de diseño impulsado por dominio. Básicamente, pensamos que nuestro sistema está respaldado por un ODBMS (con muchas fugas pequeñas :-)).
Llamé a nuestra arquitectura un "kernel de dominio" porque el libro DDD aún no se había escrito. Esto fue en los primeros días de Hibernate, por lo que el modelo de dominio no estaba contaminado con anotaciones. La preocupación separada de la persistencia se mantuvo separada en las asignaciones XML.
Una vez más, con el tiempo, hemos mejorado en empujar el comportamiento hacia abajo en la capa de dominio. Teníamos un controlador bastante tradicional -> servicio -> dao -> esquema de capas de dominio que se aplicaba con dependencias en tiempo de compilación. Lo que observé a lo largo del tiempo es que este modelo funcionó muy bien para nuestro sistema, que representaba todas las facetas del dominio bastante complejo de la administración del plan 401 (k), incluida la configuración del plan, el comercio, la contabilidad, las pruebas de cumplimiento, las ventas, la marca, etc. Un modelo de dominio enriquecido con una persistencia "mágica" (relativamente) transparente fue clave para poder construir nuevas características en términos de las características existentes en el modelo de dominio.
Nuestra capa de servicio solo organizó las interacciones entre los servicios técnicos (como correo electrónico, E / S de archivos, cola de espera, etc.) y ayudó a abarcar los paquetes de dominio cuando fue necesario. La capa de servicio también definió el límite de la transacción (a través de Spring). Los servicios solo recibieron o emitieron DTO o primitivos. Mucha gente odia eso, como una ruptura en DRY, pero descubrimos que nos mantenía honestos al definir las interfaces de servicio y el código que las usaba. También hizo muy fácil remotear las cosas más tarde.
Este enfoque nos permitió construir software de alta calidad con un equipo bastante pequeño (éramos un equipo Scrum).
Entonces, considérame un creyente en objetos de dominio persistente. No sé si mi historia ayuda, pero quería compartir.
¿Las anotaciones de persistencia en objetos de dominio son una mala práctica?
Si Con el aumento de NoSQL, no puede confiar en una sola estrategia de persistencia.
Por ejemplo, hoy estoy persistiendo mis objetos de dominio (digamos usando morphia) en MongoDB . ¿Qué pasa si mañana quiero persistir los objetos de dominio a Neo4j ?
O, uno podría querer persistir los objetos de dominio en los tres tipos de bases de datos como relacional (Postgres / MySQL), MongoDB (almacén de documentos) y Neo4J (base de datos gráfica) solo para evaluar.
En todos estos casos, es mejor tener una estrategia de persistencia separada que depender de objetos de dominio.
Mejor práctica : Pasar la estrategia persistente como un patrón de estrategia podría ayudar. Pero debes tener cuidado al diseñar tus clases / objetos.