You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Continuamos los las novedades de OpinionatedFramework. En esta entrada voy a hablar sobre cómo se manejan los comandos. Los comandos son una parte central del framework, proporcionando una manera clara y coherente de encapsular los casos de uso de tu aplicación.
Registrando el ejecutor de comandos
Para poder ejecutar comandos en OpinionatedFramework, primero necesitamos registrar un servicio que implemente el contratoICommandExecutor en nuestro contenedor.
OpinionatedFramework proporciona una implementación por defecto que se puede registrar de la siguiente manera:
También podemos tener comandos que devuelven un resultado. Por ejemplo, podríamos tener un comando que devuelve el número total de usuarios en nuestro sistema:
NOTA: Habrás notado que al utilizar el constructor para pasar parámetros al comando, no se puede inyectar servicios por constructor. Esto no es un problema ya que en el comando podemos utilizar la clase Locator para resolverlos.
Después, necesitamos resolver ICommandExecutor y llamar a su método InvokeAsync.
Opcionalmente, el framework proporciona una fachada y un método de extensión sobre la clases Command y Command<TResult>, lo que permite hace la ejecución de comandos algo más sencillo.
// Using the facadeawaitCommand.InvokeAsync(createAliceUserCommand);// Using the extension methodinttotalUsers=awaitgetTotalUsersCommand.InvokeAsync();
El método InvokeAsync, tanto del contrato, como de la fachada o el método de extensión, aceptan opcionalmente un token de cancelación que luego recibirá el comando:
El ejecutador de comandos crea un scope cuando se invoca un comando. Esto significa que cuando se resuelva un servicio scoped usando el Locator dentro de un comando, siempre obtendremos la misma instancia.
Aunque la clase Locator es estática, está diseñada para ser thread safe. Cada comando mantiene su propio scope incluso aunque se estén ejecuando varios comandos al mismo tiempo.
Middlewares
El ejecutador por defecto permite registrar middlewares que se ejecutan antes y después de cada comando. Un middleware es una clase que implementa la interfaz ICommandMiddleware:
Un middleware puede realizar acciones antes y después de la ejecución del comando, y también puede cortocircuitar el flujo de ejecución. Un ejemplo de middleware que loguea cada comando que se ejecuta utilizando la fachada Log:
publicclassLoggingMiddleware:ICommandMiddleware{publicasyncTaskExecuteAsync(CommandContextcontext,InvokeNextMiddlewareDelegatenext){Log.Info($"Executing command: {context.CommandType.Name}");awaitnext(context);// Ejecuta el siguiente middleware y, finalmente el comando.Log.Info($"Executed command: {context.CommandType.Name}");}}
Hay muchas posibles utilidades para los middleware, algunas podrían ser:
Loguear la ejecución de un comando.
Gestionar las excepciones que puede lanzar un comando, envolviendo next() en un bloque try..catch.
Comprobar que el usuario tiene permisos suficientes para ejecutar el comando y, en caso contrario, cortocircuitar el flujo.
NOTA: Los middleware también mantienen el mismo scope que el comando que va a ejecutar. Esto permite cosas como que tras realizar una acción sobre un store registrado como scoped en un comando, un middleware se encargue de persistir los cambios en el mismo store.
NOTA 2: Al llamar a next() en el último middleware, se ejecuta el comando. Se podría decir que next es el método ExecuteAsync() del siguiente middeware y, en caso de ser el último, del comando. No llamar a next() en un comando hará que ni los siguientes middleware ni el comando se ejecuten. Esto se conoce como cortocircuitar el flujo de middleware.
Para registrar un middleware, simplemente necesitamos agregarlo al CommandExecutor cuando lo registramos:
Este es el motivo por el cual hay un array en el constructor del command executor, para registrar los middleware que se ejecutarán.
Conclusión
Los comandos en OpinionatedFramework proporcionan una forma sólida y coherente de encapsular nuestra lógica de negocio, manteniendo nuestras clases y métodos limpios y enfocados. Mediante el uso de middlewares, podemos agregar funcionalidades comunes a todos nuestros comandos, como logging o manejo de errores, de manera fácil y consistente.
El manejo del scope en los comandos también es una característica poderosa, ya que nos permite garantizar que los servicios scoped se comporten de manera predecible durante la ejecución de un comando.
Me gustaría facilitar en registro del ejecutador de comandos añadiendo un método de extensión que permita registrarlo de la siguiente manera:
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Esta entrada forma parte de una serie:
Continuamos los las novedades de OpinionatedFramework. En esta entrada voy a hablar sobre cómo se manejan los comandos. Los comandos son una parte central del framework, proporcionando una manera clara y coherente de encapsular los casos de uso de tu aplicación.
Registrando el ejecutor de comandos
Para poder ejecutar comandos en OpinionatedFramework, primero necesitamos registrar un servicio que implemente el contrato
ICommandExecutor
en nuestro contenedor.OpinionatedFramework proporciona una implementación por defecto que se puede registrar de la siguiente manera:
Cuando lleguememos a la parte de middleware veremos que este array vacío que se le proporciona al constructor de la clase
CommandExecutor
.Podría personalizarse el proceso de ejecución de un comando creando nuevas implementaciones de este contrato para casos avanzados.
Creando un comando
Un comando es una clase que hereda de
Command
oCommand<TResult>
.Un comando encapsula una operación de nuestra aplicación. Por ejemplo, podríamos tener un comando para crear un nuevo usuario en nuestro sistema:
También podemos tener comandos que devuelven un resultado. Por ejemplo, podríamos tener un comando que devuelve el número total de usuarios en nuestro sistema:
Ejecutando comandos
Para ejecutar un comando, primero tenemos que crear una instancia del comando. Esto lo haremos simplemente llamando al constructor:
Después, necesitamos resolver
ICommandExecutor
y llamar a su métodoInvokeAsync
.Opcionalmente, el framework proporciona una fachada y un método de extensión sobre la clases
Command
yCommand<TResult>
, lo que permite hace la ejecución de comandos algo más sencillo.El método
InvokeAsync
, tanto del contrato, como de la fachada o el método de extensión, aceptan opcionalmente un token de cancelación que luego recibirá el comando:Servicios scoped
El ejecutador de comandos crea un scope cuando se invoca un comando. Esto significa que cuando se resuelva un servicio scoped usando el
Locator
dentro de un comando, siempre obtendremos la misma instancia.Aunque la clase Locator es estática, está diseñada para ser thread safe. Cada comando mantiene su propio scope incluso aunque se estén ejecuando varios comandos al mismo tiempo.
Middlewares
El ejecutador por defecto permite registrar middlewares que se ejecutan antes y después de cada comando. Un middleware es una clase que implementa la interfaz
ICommandMiddleware
:Un middleware puede realizar acciones antes y después de la ejecución del comando, y también puede cortocircuitar el flujo de ejecución. Un ejemplo de middleware que loguea cada comando que se ejecuta utilizando la fachada
Log
:Hay muchas posibles utilidades para los middleware, algunas podrían ser:
next()
en un bloque try..catch.Para registrar un middleware, simplemente necesitamos agregarlo al CommandExecutor cuando lo registramos:
Este es el motivo por el cual hay un array en el constructor del command executor, para registrar los middleware que se ejecutarán.
Conclusión
Los comandos en OpinionatedFramework proporcionan una forma sólida y coherente de encapsular nuestra lógica de negocio, manteniendo nuestras clases y métodos limpios y enfocados. Mediante el uso de middlewares, podemos agregar funcionalidades comunes a todos nuestros comandos, como logging o manejo de errores, de manera fácil y consistente.
El manejo del scope en los comandos también es una característica poderosa, ya que nos permite garantizar que los servicios scoped se comporten de manera predecible durante la ejecución de un comando.
Me gustaría facilitar en registro del ejecutador de comandos añadiendo un método de extensión que permita registrarlo de la siguiente manera:
Recuerda que OpinionatedFramework es un proyecto open source y puedes colaborar en su desarrollo.
¡Nos vemos!
Beta Was this translation helpful? Give feedback.
All reactions