Todavía recuerdo los viejos tiempos de repositorios. Pero los repositorios solían ponerse feos con el tiempo. Luego, CQRS se hizo popular. Eran agradables, eran un soplo de aire fresco. Pero recientemente me he estado preguntando una y otra vez por qué no mantengo la lógica correcta en el método de acción del controlador (especialmente en Web Api, donde la acción es algún tipo de controlador de comando / consulta en sí mismo).
Anteriormente tenía una respuesta clara para eso: lo hago para probar, ya que es difícil probar el Controlador con todos esos singleton inamovibles y la infraestructura ASP.NET fea en general. Pero los tiempos han cambiado y las clases de infraestructura ASP.NET son mucho más amigables con las pruebas unitarias hoy en día (especialmente en ASP.NET Core).
Aquí hay una llamada típica de WebApi: se agrega un comando y se notifica a los clientes de SignalR al respecto:
public void AddClient(string clientName)
{
using (var dataContext = new DataContext())
{
var client = new Client() { Name = clientName };
dataContext.Clients.Add(client);
dataContext.SaveChanges();
GlobalHost.ConnectionManager.GetHubContext<ClientsHub>().ClientWasAdded(client);
}
}
Puedo fácilmente probarlo / simularlo. Además, gracias a OWIN puedo configurar los servidores locales WebApi y SignalR y hacer una prueba de integración (y bastante rápido).
Recientemente me sentí cada vez menos motivado para crear engorrosos manejadores de Comandos / Consultas y tiendo a mantener el código en las acciones de Web Api. Hago una excepción solo si la lógica se repite o si es realmente complicada y quiero aislarla. Pero no estoy seguro si estoy haciendo lo correcto aquí.
¿Cuál es el enfoque más razonable para administrar la lógica en una aplicación ASP.NET moderna típica? ¿Cuándo es razonable mover su código a los controladores de Comandos y Consultas? ¿Hay mejores patrones?
Actualizar. Encontré este artículo sobre el enfoque DDD-lite. Entonces parece que mi enfoque de mover partes complicadas de código a los controladores de comandos / consultas podría llamarse CQRS-lite.
Respuestas:
¿Es CQRS un patrón relativamente complicado y costoso? Si.
¿Es sobre ingeniería? Absolutamente no.
En el artículo original donde Martin Fowler habla sobre CQRS , puede ver muchas advertencias sobre no usar CQRS donde no es aplicable:
Mi énfasis arriba.
Si su aplicación está utilizando CQRS para todo, entonces no es CQRS lo que está sobre-diseñado, es su aplicación. Este es un patrón excelente para resolver algunos problemas específicos, especialmente aplicaciones de alto rendimiento / alto volumen donde la concurrencia de escritura puede ser una preocupación importante.
Y puede que no sea la aplicación completa, sino solo una pequeña parte de ella.
Un ejemplo en vivo de mi trabajo, empleamos CQRS en el sistema de entrada de pedidos, donde no podemos perder ningún pedido, y tenemos picos en los que miles de pedidos provienen al mismo tiempo de diferentes fuentes, en algunas horas específicas. CQRS nos ayudó a mantener el sistema vivo y receptivo, al tiempo que nos permitió escalar bien los sistemas de back-end para procesar estos pedidos más rápido cuando sea necesario (más servidores de back-end) y más lento / más barato cuando no es necesario.
CQRS es perfecto para el problema en el que hay varios actores que colaboran en el mismo conjunto de datos o escriben en el mismo recurso.
Aparte de eso, difundir un patrón hecho para resolver un solo problema a todos tus problemas solo creará más problemas para ti.
Algunos otros enlaces útiles:
http://udidahan.com/2011/04/22/when-to-avoid-cqrs/
http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/
fuente
CQRS no es un reemplazo uno por uno para los repositorios, exactamente porque es un patrón complejo y costoso que solo es útil en algunos casos.
Esto es lo que Udi Dahan tiene que decir en mérito:
( fuente )
Martin Fowler:
( fuente )
Finalmente, Greg Young:
( fuente )
fuente