La separación de comandos y consultas ( CQS ) es un principio de la programación imperativa . Fue ideado por Bertrand Meyer como parte de su trabajo pionero en el lenguaje de programación Eiffel .
Establece que cada método debe ser un comando que realiza una acción o una consulta que devuelve datos al llamador, pero no ambas cosas. En otras palabras, hacer una pregunta no debe cambiar la respuesta . [ 1 ] De manera más formal, los métodos deben devolver un valor solo si son referencialmente transparentes y, por lo tanto, no tienen efectos secundarios .
Conexión con el diseño por contrato
La separación de comandos y consultas resulta especialmente adecuada para la metodología de diseño por contrato (DbC), en la que el diseño de un programa se expresa mediante aserciones integradas en el código fuente , que describen el estado del programa en momentos críticos. En DbC, las aserciones se consideran anotaciones de diseño —no lógica del programa— y, por lo tanto, su ejecución no debería afectar al estado del programa. La separación de comandos y consultas (CQS) es beneficiosa para DbC porque cualquier método que devuelva un valor (cualquier consulta) puede ser llamado por cualquier aserción sin temor a modificar el estado del programa.
En términos teóricos, esto establece un grado de coherencia que permite razonar sobre el estado de un programa sin modificarlo simultáneamente. En la práctica, CQS permite omitir todas las comprobaciones de aserción en un sistema en funcionamiento para mejorar su rendimiento sin modificar inadvertidamente su comportamiento. CQS también puede prevenir la aparición de ciertos tipos de errores críticos .
Impacto más amplio en la ingeniería de software
Más allá de su relación con el diseño por contrato, los defensores de CQS consideran que tiene un efecto simplificador en un programa, haciendo que sus estados (mediante consultas) y cambios de estado (mediante comandos) sean más comprensibles.
CQS se adapta bien a la metodología orientada a objetos , pero también puede aplicarse fuera de la programación orientada a objetos. Dado que la separación entre efectos secundarios y valores de retorno no es inherente a la orientación a objetos, CQS puede aplicarse con éxito a cualquier paradigma de programación que requiera razonar sobre efectos secundarios.
Segregación de responsabilidades de comandos y consultas
La segregación de responsabilidades de comandos y consultas ( CQRS ) generaliza CQS a los servicios, a nivel de arquitecturas: aplica el principio CQS mediante el uso de interfaces de consulta y comando separadas y, por lo general, modelos de datos para recuperar y modificar datos, respectivamente. [ 2 ] [ 3 ]
Otros patrones arquitectónicos
- A medida que nos alejamos de una única representación con la que interactuamos a través de operaciones CRUD , podemos pasar fácilmente a una interfaz de usuario basada en tareas.
- CQRS se adapta bien a los modelos de programación basados en eventos. Es común ver un sistema CQRS dividido en servicios separados que se comunican mediante Event Collaboration. Esto permite que estos servicios aprovechen fácilmente la arquitectura orientada a eventos .
- El hecho de contar con modelos separados plantea interrogantes sobre la dificultad de mantener la coherencia entre ellos, lo que aumenta la probabilidad de recurrir a la consistencia eventual.
- En muchos dominios, gran parte de la lógica necesaria se aplica al realizar actualizaciones, por lo que puede ser conveniente utilizar la derivación de lectura anticipada para simplificar los modelos del lado de la consulta.
- Si el modelo de escritura genera eventos para todas las actualizaciones, puede estructurar los modelos de lectura como Event Posters, lo que permite que sean imágenes en memoria y, por lo tanto, evita muchas interacciones con la base de datos.
- CQRS es adecuado para dominios complejos, del tipo que también se beneficia del Diseño Orientado al Dominio . [ 3 ]
Limitaciones
CQS puede introducir complejidades a la hora de implementar correctamente software reentrante y multihilo . Esto suele ocurrir cuando se utiliza un patrón que no es seguro para subprocesos al implementar la separación entre comandos y consultas.
Aquí hay un ejemplo simple que no sigue CQS, pero es útil para software multihilo porque resuelve la complejidad del bloqueo para todas las demás partes del programa, pero al hacerlo no sigue CQS porque la función modifica el estado y lo devuelve:
private int x ; public int incrementAndReturnX () { lock x ; // mediante algún mecanismo x = x + 1 ; int x_copy = x ; unlock x ; // mediante algún mecanismo return x_copy ; }Aquí hay una versión compatible con CQS. Tenga en cuenta que solo se puede usar de forma segura en aplicaciones de un solo hilo. En un programa multihilo, existe una condición de carrera en la función que realiza la llamada, entre donde se llamaría a increment()y :value()
privado int x ; público int valor () { return x ; } void incremento () { x = x + 1 ; }Incluso en programas de un solo hilo, a veces resulta significativamente más conveniente tener un método que combine consulta y comando. Martin Fowler cita el pop()método de una pila como ejemplo. [ 4 ]
Véase también
Referencias
- ↑ Meyer, Bertrand. "Eiffel: un lenguaje para la ingeniería de software" (PDF) . pág. 22. Consultado el 16 de diciembre de 2014 .
- ↑ Young, Greg. "Documentos CQRS" (PDF) . Consultado el 28 de diciembre de 2012 .
- 1 2 Fowler, Martin. "CQRS" . Recuperado el 14 de julio de 2011 .
- ↑ Fowler, Martin. "CommandQuerySeparation" . Consultado el 5 de diciembre de 2005 .
Lecturas adicionales
- Meyer, Bertrand (septiembre de 1994) [1988]. Construcción de software orientado a objetos . Prentice Hall. ISBN 0-13-629049-3.
Enlaces externos
- Explicación sobre el Bliki de Martin Fowler
- Principios de programación
- Programación orientada a objetos