La separación de comandos y consultas ( CQS ) es un principio de programación informática imperativa . Fue ideado por Bertrand Meyer como parte de su trabajo pionero en el lenguaje de programación Eiffel .
Se establece que cada método debe ser un comando que realiza una acción o una consulta que devuelve datos al autor de la llamada, pero no ambos. 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 .
La separación de comandos y consultas es particularmente adecuada para una metodología de diseño por contrato (DbC), en la que el diseño de un programa se expresa como afirmaciones integradas en el código fuente , que describen el estado del programa en ciertos momentos críticos. En DbC, las afirmaciones se consideran anotaciones de diseño (no lógica del programa) y, como tales, su ejecución no debería afectar el estado del programa. CQS es beneficioso para DbC porque cualquier método que devuelva valores (cualquier consulta) puede ser llamado por cualquier afirmación sin temor a modificar el estado del programa.
En términos teóricos, esto establece una medida de cordura, por la cual uno puede razonar sobre el estado de un programa sin modificar simultáneamente ese estado. En términos prácticos, CQS permite que se omitan 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 de Heisen .
Más allá de la conexión con el diseño por contrato, sus partidarios consideran que CQS tiene un efecto simplificador en un programa, haciendo que sus estados (a través de consultas) y cambios de estado (a través de comandos) sean más comprensibles. [ cita requerida ]
El CQS es adecuado para la metodología orientada a objetos , pero también se puede aplicar fuera de la programación orientada a objetos. Dado que la separación de los efectos secundarios y los valores de retorno no es inherentemente orientada a objetos, el CQS se puede aplicar de manera rentable a cualquier paradigma de programación que requiera razonar sobre los efectos secundarios. [ cita requerida ]
La segregación de responsabilidad de consulta de comando ( 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, generalmente, modelos de datos para recuperar y modificar datos, respectivamente. [2] [3]
El CQS puede generar complejidades a la hora de implementar correctamente software reentrante y multiproceso . Esto suele ocurrir cuando se utiliza un patrón no seguro para subprocesos para implementar la separación de comandos y consultas.
He aquí un ejemplo simple que no sigue CQS, pero es útil para software multiproceso porque resuelve la complejidad del bloqueo para todas las demás partes del programa, pero al hacerlo no sigue CQS porque la función muta el estado y lo devuelve:
privado int x ; público int incrementAndReturnX () { bloquear x ; // por algún mecanismo x = x + 1 ; int x_copy = x ; desbloquear x ; // por algún mecanismo devolver x_copy ; }
A continuación se muestra una versión compatible con CQS. Tenga en cuenta que solo se puede usar de forma segura en aplicaciones de un solo subproceso. En un programa de múltiples subprocesos, hay una condición de carrera en el llamador, entre donde increment()
y value()
se llamaría:
int privado x ; int público valor () { devolver x ; } void incremento () { x = x + 1 ; }
Incluso en programas de un solo subproceso, a veces es mucho más conveniente tener un método que sea una combinación de consulta y comando. Martin Fowler cita el pop()
método de una pila como ejemplo. [4]