Estoy (re) diseñando una aplicación a gran escala, utilizamos una arquitectura multicapa basada en DDD.
Tenemos MVC con capa de datos (implementación de repositorios), capa de dominio (definición de modelo de dominio e interfaces - repositorios, servicios, unidad de trabajo), capa de servicio (implementación de servicios). Hasta ahora, usamos modelos de dominio (en su mayoría entidades) en todas las capas, y usamos DTO solo como modelos de vista (en el controlador, el servicio devuelve modelos de dominio y el controlador crea el modelo de vista, que se pasa a la vista).
He leído innumerables artículos sobre el uso, no uso, mapeo y paso de DTO. Entiendo que no hay una respuesta definitiva, pero no estoy seguro de si está bien o no devolver los modelos de dominio de los servicios a los controladores. Si devuelvo el modelo de dominio, todavía nunca se pasa a la vista, ya que el controlador siempre crea un modelo de vista específico de la vista; en este caso, parece legítimo. Por otro lado, no se siente bien cuando el modelo de dominio abandona la capa empresarial (capa de servicio). A veces, el servicio debe devolver el objeto de datos que no se definió en el dominio y luego tenemos que agregar un nuevo objeto al dominio que no está asignado o crear un objeto POCO (esto es feo, ya que algunos servicios devuelven modelos de dominio, algunos efectivamente devolver DTO).
La pregunta es: si usamos estrictamente modelos de vista, ¿está bien devolver los modelos de dominio a los controladores, o deberíamos usar siempre DTO para la comunicación con la capa de servicio? Si es así, ¿está bien ajustar los modelos de dominio en función de qué servicios necesitan? (Francamente, no lo creo, ya que los servicios deberían consumir lo que tiene el dominio). Si debemos apegarnos estrictamente a los DTO, ¿deberían definirse en la capa de servicio? (Creo que sí). A veces está claro que deberíamos usar DTO (por ejemplo, cuando el servicio realiza mucha lógica de negocios y crea nuevos objetos), a veces está claro que deberíamos usar solo modelos de dominio (por ejemplo, cuando el servicio de Membresía devuelve Usuario anémico ( s), parece que no tendría mucho sentido crear DTO que sea lo mismo que el modelo de dominio), pero prefiero la coherencia y las buenas prácticas.
Article Domain vs DTO vs ViewModel - ¿Cómo y cuándo usarlos? (y también algunos otros artículos) es muy similar a mi problema, pero no responde a esta (s) pregunta (s). Artículo ¿Debo implementar DTO en el patrón de repositorio con EF? también es similar, pero no trata con DDD.
Descargo de responsabilidad: no tengo la intención de usar ningún patrón de diseño solo porque existe y es elegante, por otro lado, me gustaría usar buenos patrones de diseño y prácticas también porque ayuda a diseñar la aplicación en su conjunto, ayuda con la separación De preocupación, incluso si usar un patrón particular no es "necesario", al menos por el momento.
Como siempre, gracias.
fuente
Respuestas:
Te hace sentir como si estuvieras sacando las tripas, ¿verdad? Según Martin Fowler: la capa de servicio define los límites de la aplicación, encapsula el dominio. En otras palabras, protege el dominio.
¿Puede proporcionar un ejemplo de este objeto de datos?
Sí, porque la respuesta es parte de su capa de servicio. Si se define "en otro lugar", la capa de servicio debe hacer referencia a ese "otro lugar", agregando una nueva capa a su lasaña.
Un DTO es un objeto de respuesta / solicitud, tiene sentido si lo usa para la comunicación. Si usa modelos de dominio en su capa de presentación (MVC-Controllers / View, WebForms, ConsoleApp), entonces la capa de presentación está estrechamente acoplada a su dominio, cualquier cambio en el dominio requiere que cambie sus controladores.
Esta es una de las desventajas de DTO para nuevos ojos. Ahora mismo estas pensando duplicación de código , pero a medida que su proyecto se expanda, tendría mucho más sentido, especialmente en un entorno de equipo donde se asignan diferentes equipos a diferentes capas.
DTO puede agregar complejidad adicional a su aplicación, pero también lo son sus capas. DTO es una característica costosa de su sistema, no son gratis.
¿Por qué usar un DTO?
Este artículo proporciona ventajas y desventajas de usar un DTO, http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html
Resumen de la siguiente manera:
Cuándo usar
Cuando no usar
Argumentos contra DTO
Argumentos Con DTO
fuente
Parece que su aplicación es lo suficientemente grande y compleja, ya que ha decidido adoptar el enfoque DDD. No devuelva sus entidades poco o las llamadas entidades de dominio y objetos de valor en su capa de servicio. Si desea hacer esto, elimine su capa de servicio porque ya no la necesita. Los objetos Ver modelo o transferencia de datos deben vivir en la capa de servicio porque deben asignarse a miembros del modelo de dominio y viceversa. Entonces, ¿por qué necesitas tener DTO? En una aplicación compleja con muchos escenarios, debe separar las preocupaciones del dominio y sus vistas de presentación, un modelo de dominio podría dividirse en varios DTO y también varios modelos de Dominio podrían colapsarse en un DTO. Por lo tanto, es mejor crear su DTO en una arquitectura en capas, incluso si fuera el mismo que su modelo.
¿Deberíamos usar siempre DTO para la comunicación con la capa de servicio? Sí, debe devolver DTO por su capa de servicio, ya que ha hablado con su repositorio en la capa de servicio con los miembros del modelo de dominio y asignarlos a DTO y regresar al controlador MVC y viceversa.
¿Está bien ajustar los modelos de dominio en función de los servicios que necesitan? Un servicio solo habla con el repositorio y los métodos de dominio y los servicios de dominio, debe resolver el negocio en su dominio en función de sus necesidades y no es la tarea del servicio decirle al dominio lo que se necesita.
Si deberíamos apegarnos estrictamente a los DTO, ¿deberían definirse en la capa de servicio? Sí, intente tener DTO o ViewModel solo en el servicio más adelante porque deberían asignarse a los miembros del dominio en la capa de servicio y no es una buena idea colocar DTO en los controladores de su aplicación (intente usar el patrón Solicitar respuesta en su capa de Servicio), saludos !
fuente
En mi experiencia, deberías hacer lo que sea práctico. "El mejor diseño es el diseño más simple que funciona" - Einstein. Con eso es mente ...
¡Absolutamente está bien! Si tiene entidades de dominio, DTO y modelos de vista, incluidas las tablas de base de datos, tiene todos los campos de la aplicación repetidos en 4 lugares. He trabajado en grandes proyectos donde las Entidades de dominio y los Modelos de vista funcionaron bien. La única excepción a esto es si la aplicación se distribuye y la capa de servicio reside en otro servidor, en cuyo caso se requiere que los DTO envíen a través del cable por razones de serialización.
En general, estaría de acuerdo y diría que no, porque el modelo de Dominio generalmente es un reflejo de la lógica de negocios y, por lo general, el consumidor no lo configura.
Si decide usarlos, estoy de acuerdo y le digo que sí, la capa de Servicio es el lugar perfecto, ya que devuelve los DTO al final del día.
¡Buena suerte!
fuente
Llego tarde a esta fiesta, pero esta es una pregunta tan común e importante que me sentí obligado a responder.
¿Por "servicios" se refiere a la "Capa de aplicación" descrita por Evan en el libro azul ? Voy a asumir que lo hace, en cuyo caso la respuesta es que deben no volver dtos. Sugiero leer el capítulo 4 del libro azul, titulado "Aislar el dominio".
En ese capítulo, Evans dice lo siguiente sobre las capas:
Hay una buena razón para esto. Si usa el concepto de orden parcial como una medida de la complejidad del software , tener una capa que dependa de una capa superior aumenta la complejidad, lo que disminuye la capacidad de mantenimiento.
Aplicando esto a su pregunta, los DTO son realmente un adaptador que es una preocupación de la capa de interfaz de usuario / presentación. Recuerde que la comunicación remota / entre procesos es exactamente el propósito de un DTO (vale la pena señalar que en esa publicación Fowler también argumenta en contra de que los DTO sean parte de una capa de servicio, aunque no necesariamente habla el lenguaje DDD).
Si su capa de aplicación depende de esos DTO, depende de una capa por encima de sí misma y su complejidad aumenta. Puedo garantizar que esto aumentará la dificultad de mantener su software.
Por ejemplo, ¿qué sucede si su sistema interactúa con varios otros sistemas o tipos de clientes, cada uno de los cuales requiere su propio DTO? ¿Cómo sabe qué DTO debe devolver un método de su servicio de aplicación? ¿Cómo resolvería ese problema si su idioma de elección no permite sobrecargar un método (método de servicio, en este caso) basado en el tipo de retorno? E incluso si encuentra una manera, ¿por qué violar su capa de aplicación para admitir una preocupación de la capa de presentación?
En términos prácticos, este es un paso por un camino que terminará en una arquitectura de espagueti. He visto este tipo de devolución y sus resultados en mi propia experiencia.
Donde actualmente trabajo, los servicios en nuestra capa de aplicación devuelven objetos de dominio. No consideramos que esto sea un problema ya que la capa de interfaz (es decir, UI / Presentación) depende de la capa de dominio, que está debajo de ella. Además, esta dependencia se minimiza a un tipo de dependencia "solo de referencia" porque:
a) la capa de interfaz solo puede acceder a estos objetos de dominio como valores de retorno de solo lectura obtenidos mediante llamadas a la capa de aplicación
b) los métodos de los servicios en la capa de aplicación aceptan como entrada solo entrada "en bruto" (valores de datos) o parámetros de objeto (para reducir el recuento de parámetros cuando sea necesario) definidos en esa capa. Específicamente, los servicios de aplicaciones nunca aceptan objetos de dominio como entrada.
La capa de interfaz utiliza técnicas de mapeo definidas dentro de la propia capa de interfaz para mapear desde objetos de dominio a DTO. Nuevamente, esto mantiene a los DTO enfocados en ser adaptadores controlados por la capa de interfaz.
fuente
Tarde a la fiesta, pero me enfrento al mismo tipo de arquitectura y me estoy inclinando hacia "solo DTOs del servicio". Esto se debe principalmente a que he decidido usar solo objetos / agregados de dominio para mantener la validez dentro del objeto, por lo tanto, solo al actualizar, crear o eliminar. Cuando consultamos datos, solo usamos EF como depósito y asigna el resultado a los DTO. Esto nos permite optimizar las consultas de lectura y no adaptarlas a los objetos comerciales, a menudo utilizando funciones de base de datos, ya que son rápidas.
Cada método de servicio define su propio contrato y, por lo tanto, es más fácil de mantener con el tiempo. Espero.
fuente
Dado que el modelo de dominio proporciona terminología ( lenguaje ubicuo ) para toda su aplicación, es mejor utilizar el Modelo de dominio ampliamente.
La única razón para usar ViewModels / DTO es una implementación del patrón MVC en su aplicación para separar
View
(cualquier tipo de capa de presentación) yModel
(Modelo de dominio). En este caso, su presentación y modelo de dominio están poco vinculados.Supongo que usted habla sobre los servicios de Aplicación / Negocio / Dominio lógico.
Le sugiero que devuelva las entidades de dominio cuando pueda. Si es necesario devolver información adicional, es aceptable devolver DTO que contenga varias entidades de dominio.
A veces, las personas que usan marcos de tercera parte, que generan proxies sobre entidades de dominio, enfrentan dificultades para exponer entidades de dominio de sus servicios, pero es solo una cuestión de uso incorrecto.
Yo diría que es suficiente para devolver entidades de dominio en el 99,9% de los casos.
Para simplificar la creación de DTO y mapear sus entidades de dominio en ellos, puede usar AutoMapper .
fuente
Si devuelve parte de su modelo de dominio, se convierte en parte de un contrato. Es difícil cambiar un contrato, ya que las cosas fuera de su contexto dependen de él. Como tal, haría que parte de su modelo de dominio sea difícil de cambiar.
Un aspecto muy importante de un modelo de dominio es que es fácil de cambiar. Esto nos hace flexibles a los requisitos cambiantes del dominio.
fuente
Sugeriría analizar estas dos preguntas:
¿Sus capas superiores (es decir, ver y ver modelos / controladores) consumen los datos de una manera diferente de lo que expone la capa de dominio? Si se está realizando una gran cantidad de mapeo o incluso si hay lógica involucrada, sugeriré volver a visitar su diseño: probablemente debería estar más cerca de cómo se usan realmente los datos.
¿Qué tan probable es que cambies profundamente tus capas superiores? (por ejemplo, cambiar ASP.NET por WPF). Si esto es muy diferente y su arquitectura no es muy compleja, es mejor que exponga tantas entidades de dominio como sea posible.
Me temo que es un tema bastante amplio y realmente se reduce a lo complejo que es su sistema y sus requisitos.
fuente
En mi experiencia, a menos que esté utilizando un patrón de interfaz de usuario OO (como objetos desnudos), exponer los objetos de dominio a la interfaz de usuario es una mala idea. Esto se debe a que a medida que la aplicación crece, las necesidades de la interfaz de usuario cambian y obligan a sus objetos a acomodar esos cambios. Terminas sirviendo a 2 maestros: UI y DOMAIN, que es una experiencia muy dolorosa. Créeme, no quieres estar allí. El modelo de IU tiene la función de comunicarse con el usuario, el modelo DOMAIN para mantener las reglas de negocio y el modelo de persistencia se ocupa de almacenar datos de manera efectiva. Todos abordan diferentes necesidades de la aplicación. Estoy escribiendo una publicación de blog sobre esto, la agregaré cuando esté lista.
fuente