c# - net - En CQRS, ¿debería mi lado de lectura devolver DTO o ViewModels?
net core ddd (4)
Estoy teniendo un debate con mis compañeros de trabajo en el diseño del lado de lectura de una aplicación CQRS.
Opción 1: el lado de lectura de la aplicación de mi aplicación CQRS devuelve DTO, por ejemplo:
public interface IOrderReadService
{
public OrderDto Load(int id);
}
public class SomeController
{
public ActionResult SomeAction(int id)
{
var dto = ObjectFactory.GetInstance<IOrderReadService>().Load(id);
var viewModel = Mapper.Map<OrderDto, SomeViewModel>();
return View(viewModel);
}
}
public class SomeOtherController
{
public ActionResult SomeOtherAction(int id)
{
var dto = ObjectFactory.GetInstance<IOrderReadService>().Load(id);
var viewModel = Mapper.Map<OrderDto, SomeOtherViewModel>();
return View(viewModel);
}
}
Opción 2: el lado de lectura de la aplicación devuelve ViewModels, por ejemplo:
public interface IOrderReadService
{
public SomeViewModel LoadSomething(int id);
public SomeOtherViewModel LoadSomethingElse(int id);
}
public class SomeController
{
public ActionResult SomeAction(int id)
{
return View(ObjectFactory.GetInstance<IOrderReadService>().LoadSomething(id));
}
}
public class SomeOtherController
{
public ActionResult SomeOtherAction(int id)
{
return View(ObjectFactory.GetInstance<IOrderReadService>().LoadSomethingElse(id));
}
}
A partir de la investigación que mis compañeros de trabajo y yo hemos hecho al respecto, las respuestas parecen mixtas, parece que realmente depende del contexto. Así que te pregunto, mi querido StackOverflowians:
¿Un enfoque parece tener ventajas claras sobre el otro? Si es así, ¿Que son?
El consejo general es una proyección por pantalla (Greg Young) o incluso una proyección por widget (si entiendo a Udi Dahan correctamente).
Para consolidar los modelos de lectura en DTO que una vez más tienen que mapearse en vistas separadas, se contradice todo el propósito de un modelo de lectura optimizado. Agrega pasos de complejidad y mapeo que tratamos de eliminar en primer lugar.
Mi consejo: intente acercarse lo más posible a SELECT * FROM ViewSpecificTable [WHERE ...]
o algo similar si usa NoSQL en su capa de lectura delgada.
El concepto de Aggregate Roots y sus "hijos" no tiene demasiada implicación en el lado de lectura, ya que estos son conceptos de modelo de dominio. No desea tener un modelo de dominio en el lado de lectura, solo existe en el lado de escritura.
La transformación específica de la plataforma de UI mencionada por Mohamed Abed se debe hacer en la capa de UI, no en el modelo de lectura en sí.
Larga historia corta: optaría por la opción 2. Para no confundirla con un ViewModel
específico de la ViewModel
, prefiero llamarlo ReadModel
pero tengo uno por vista de todos modos.
Preferiría devolver DTO para separar la capa de aplicación de la tecnología de presentación (porque cada tecnología de presentación puede tener algunos requisitos sobre la estructura del modelo de presentación), por ejemplo, un enlace de aplicación web MVC es diferente al enlace MVVM de WPF, también puede requerir algunas propiedades / campos en los modelos de vista que no tienen nada que ver con los datos de la aplicación, como por ejemplo (SliderWidth o IsEmailFieldEnabled, ...). También, por ejemplo, si utilizo WPF MVVM, necesitaría implementar la interfaz INotifyPropertyChanged para permitir el enlace, no es conveniente ni está relacionado con implementar esta interfaz en el servicio de lectura de la aplicación.
por lo que preferiría separar la preocupación de la representación de datos leídos de la tecnología de presentación real y el modelo de visualización.
Entonces la opción 1 es mejor para mí
Un modelo de lectura es una proyección del modelo de escritura. Está ahí para cumplir un propósito específico. En su caso, parece que proporciona modelos de vista a sus controladores MVC. Como tal, ¿por qué pasar por el problema de mapear DTO a Viewmodels? La única razón por la que podía pensar era que el beneficio de tener dos modelos de lectura separados podría no sobrepasar su costo de mantenimiento. Pero considere que la "fusión" de los modelos de lectura con el fin de "reutilizar" y "reducir los costos de mantenimiento" aumenta la complejidad para el desarrollador (¿Puedo cambiar esta tabla? Hmmm, ahora tengo dos (o más) consumidores que tengo que tomar en cuenta cuenta - huele un poco como la integración de la base de datos otra vez).
Sólo mis pensamientos.
Uno de los principios principales de DDD / CQRS es que no debe editar el modelo de vista. En cambio, las pantallas basadas en tareas deben guiar al usuario hacia la emisión de comandos explícitos. Si no puede crear pantallas basadas en tareas, debe usar una forma diferente de CQRS como la que describo aquí:
http://udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere/