Me estoy sumergiendo en los conceptos del diseño controlado por dominio (DDD) y encontré algunos principios extraños, especialmente con respecto al aislamiento del dominio y el modelo de persistencia. Aquí está mi comprensión básica:
- Un servicio en la capa de aplicación (que proporciona un conjunto de características) solicita objetos de dominio de un repositorio que necesita para llevar a cabo su función.
- La implementación concreta de este repositorio obtiene datos del almacenamiento para el que se implementó
- El servicio le dice al objeto de dominio, que encapsula la lógica de negocios, que realice ciertas tareas que modifican su estado.
- El servicio le dice al repositorio que persista el objeto de dominio modificado.
- El repositorio necesita asignar el objeto de dominio nuevamente a la representación correspondiente en el almacenamiento.
Ahora, dados los supuestos anteriores, lo siguiente parece incómodo:
Anuncio 2 .:
El modelo de dominio parece cargar todo el objeto de dominio (incluidos todos los campos y referencias), incluso si no son necesarios para la función que lo solicitó. La carga completa podría no ser posible si se hace referencia a otros objetos de dominio, a menos que cargue también esos objetos de dominio y todos los objetos a los que hacen referencia, y así sucesivamente. Me viene a la mente la carga diferida, lo que, sin embargo, significa que comienza a consultar los objetos de su dominio, que deberían ser responsabilidad del repositorio en primer lugar.
Dado este problema, la forma "correcta" de cargar objetos de dominio parece tener una función de carga dedicada para cada caso de uso. Estas funciones dedicadas solo cargarían los datos requeridos por el caso de uso para el que fueron diseñados. Aquí es donde entra en juego la incomodidad: en primer lugar, tendría que mantener una cantidad considerable de funciones de carga para cada implementación del repositorio, y los objetos de dominio terminarían en estados incompletos null
en sus campos. Esto último técnicamente no debería ser un problema porque si un valor no se cargó, no debería ser requerido por la funcionalidad que lo solicitó de todos modos. Aún así es incómodo y un peligro potencial.
Anuncio 3 .:
¿Cómo verificaría un objeto de dominio las restricciones de unicidad en la construcción si no tiene ninguna noción del repositorio? Por ejemplo, si quisiera crear un nuevo User
con un número de seguridad social único (que se proporciona), el conflicto más temprano ocurriría al pedirle al repositorio que guarde el objeto, solo si hay una restricción de unicidad definida en la base de datos. De lo contrario, podría buscar un User
con la seguridad social dada e informar un error en caso de que exista, antes de crear uno nuevo. Pero entonces las comprobaciones de restricciones vivirían en el servicio y no en el objeto de dominio al que pertenecen. Me acabo de dar cuenta de que los objetos de dominio pueden usar repositorios (inyectados) para la validación.
Anuncio 5 .:
Percibo la asignación de objetos de dominio a un backend de almacenamiento como un proceso de trabajo intensivo en comparación con hacer que los objetos de dominio modifiquen los datos subyacentes directamente. Es, por supuesto, un requisito previo esencial para desacoplar la implementación de almacenamiento concreto del código de dominio. Sin embargo, ¿realmente tiene un costo tan alto?
Aparentemente tiene la opción de usar herramientas ORM para hacer el mapeo por usted. Sin embargo, esto a menudo requeriría que diseñe el modelo de dominio de acuerdo con las restricciones de ORM, o incluso que introduzca una dependencia del dominio a la capa de infraestructura (mediante el uso de anotaciones de ORM en los objetos de dominio, por ejemplo). También he leído que los ORM introducen una sobrecarga computacional considerable.
En el caso de las bases de datos NoSQL, para las cuales casi no existen conceptos similares a ORM, ¿cómo hace un seguimiento de qué propiedades cambiaron en los modelos de dominio save()
?
Editar : Además, para que un repositorio acceda al estado del objeto de dominio (es decir, el valor de cada campo), el objeto de dominio debe revelar su estado interno que rompe la encapsulación.
En general:
- ¿A dónde iría la lógica transaccional? Esto es ciertamente persistencia específica. Es posible que algunas infraestructuras de almacenamiento ni siquiera admitan transacciones (como los repositorios simulados en memoria).
- Para las operaciones masivas que modifican múltiples objetos, ¿tendría que cargar, modificar y almacenar cada objeto individualmente para pasar por la lógica de validación encapsulada del objeto? Eso se opone a ejecutar una sola consulta directamente en la base de datos.
Agradecería alguna aclaración sobre este tema. ¿Son correctas mis suposiciones? Si no, ¿cuál es la forma correcta de abordar estos problemas?