miércoles, abril 05, 2017

Consultas y comandos

La mayoría de las aplicaciones en las que trabajo siguen un patrón. Son aplicaciones web que tienen consultas y comandos, ya sea acciones con los métodos HTTP GET o POST. Viene siendo el viejo y conocido patrón CQRS. No inició directamente con el patrón en mente; pero cuando el controlador empieza a tener mucho código en una acción, ahí es donde suena como buena idea introducir un comando o un consulta.



Imagina que estás desarrollando una aplicación para capturar ordenes de trabajo, la aplicación es solo un ejemplo por lo que las reglas serán básicas. Los requerimientos pueden ser los siguientes:
  1. Capturar orden de trabajo
  2. Consultar orden de trabajo
  3. Cambiar el estatus de la orden
  4. Marcar como pagada la orden
  5. Consultar ordenes de trabajo pendientes
Puedes ver que la mayoría son consultas o comandos; pero no inicies el desarrollo de la aplicación usando el patron por todos lados, deja que sea el código el que te diga cuando se necesita introducir una nueva abstracción. Al principio agregarías un OrdersController que use algo como EntityFramework con acciones para cada uno de los requerimientos. Y veras si el código se ve fácil de seguir.

Probablemente te pedirán que al momento de capturar una orden no solo se guarde en la db, sino que también hay que enviar correos, agregar un registro en algún log, realizar ciertas validaciones, etcetera. Si metes todo ese código en el action del controller será difícil seguir el código. Ahí es donde abstraer la creación de la orden en un comando tiene sentido. Lo que puedes hacer es agregar una clase "CreateOrderCommand" que seguramente tendría un método Execute que recibe como parámetro un objeto del tipo CreateOrderModel con toda la información necesaria para crear una orden. Este método puede regresar un objeto del tipo CommandResult que es un objeto con una lista de errores y un objeto con el resultado del comando (en este caso, puede ser una nueva orden). De este modo es fácil ver y modificar todo lo que se necesita para crear una orden en un solo lugar, sin tener que ver detalles de HTTP o del framework MVC. Es sencillo ver qué es lo que necesita el comando para funcionar correctamente.

Lo mismo puede pasar para las consultas, si la consulta es compleja será buena idea encapsularla dentro de un objeto Query que tenga propiedades con los posibles parámetros para la consulta y un método Execute o Find que regrese el resultado de la consulta.

Seguir este patrón también me ha servido cuando no conozco o no tengo control sobre la base de datos del sistema. Puedo ir armando los comandos y consultas que regresan valores fijos de prueba y construir la aplicación aunque aún no tenga acceso a la DB o aun no sepa de donde obtener los datos. Una vez que sé de donde consultar o qué actualizar puedo simplemente cambiar la clase consulta y comando indicado.

Seguir este patron cumple mejor con el principio de responsabilidad única, en lugar de tener una clase gigante "Repository" que hace todas la consultas y todos los comandos, tengo una clase comando o consulta para cada característica de la aplicación.

1 comentario:

  1. Divide 'n conquer, muy buen articulo.

    ResponderEliminar