Command–query separation

De Wikipedia, la enciclopedia libre

Command–query separation (CQS), en castellano Separación de comandos y consultas, es un principio de la programación orientada a objetos. Fue ideado por Bertrand Meyer como parte de su trabajo pionero sobre el lenguaje de programación Eiffel.

El principio afirma que cada método debe ser un comando que realiza una acción, o una consulta que devuelve datos al llamante, pero no ambos. En otras palabras, hacer una pregunta no debe cambiar la respuesta. Más formalmente, los métodos deben devolver un valor sólo si son referencialmente transparentes y, por tanto, no poseen efectos colaterales. Es de destacar que la aplicación rígida de esta especificación hace que el seguimiento del número de veces que las consultas han sido emitidos sea esencialmente imposible; está claramente destinado como una guía de programación en lugar de una regla para una buena codificación, como la de evitar el uso de un GOTO desde un bucle anidado.

Conexión con el diseño por contrato[editar]

Command–query separation está particularmente bien adaptado a una metodología de diseño por contrato (DbC), en la que el diseño de un programa se expresa como aserciones incluidas en el código fuente, que describen el estado del programa en determinados momentos críticos. En DbC, las aserciones se consideran anotaciones de diseño - no lógica del programa - y como tal, su ejecución no debería afectar al estado del programa. CQS es beneficioso para el DbC porque cualquier método que retorna valores (cualquier consulta) puede ser llamado por cualquier aserción sin temor a modificar el estado del programa.

En términos teóricos, esto establece una medida de sensatez, por la que se puede razonar sobre el estado de un programa sin modificar al mismo tiempo ese estado. En términos prácticos, CQS permite que todas las comprobaciones de aserciones puedan ser pasadas por alto en un sistema de trabajo para mejorar su rendimiento sin inadvertidamente modificar su comportamiento. CQS también puede prevenir la aparición de ciertos tipos de heisenbugs.

Impacto más amplio en la ingeniería de software[editar]

Incluso más allá de la conexión con el diseño por contrato, los seguidores de CQS consideran que tiene un efecto de simplificación 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, tanto como el que la amonestación de Edsger Dijkstra contra sentencias goto hizo para el flujo de control.

CQS está bien adaptado a la metodología orientada a objetos, pero también se puede aplicar fuera de la programación orientada a objetos. No hay nada intrínsecamente orientado a objetos sobre la separación de efectos colaterales y valores de retorno, y así CQS puede aplicarse con provecho a cualquier paradigma de programación que requiere razonamiento sobre los efectos colaterales.

Command Query Responsibility Segregation[editar]

Command Query Responsibility Segregation (CQRS) aplica el principio CQS utilizando objetos Query y Command independientes para recuperar y modificar datos, respectivamente.[1][2]

Inconvenientes[editar]

CQS puede hacer que sea más difícil la implementación de software reentrante y multihilo correctamente. Esto suele ocurrir cuando un patrón no-thread-safe se utiliza para implementar la command query separation.

Un simple ejemplo de un patrón que rompe CQS pero es útil para software multi-hilo:

private int x;
public int increment_and_return_x()
{
  lock x;   // por algún mecanismo
  x = x + 1;
  int x_copy = x;
  unlock x; // por algún mecanismo
  return x_copy;
}

Un patrón CQS común utilizable sólo en aplicaciones de un solo hilo:

private int x;
public int value()
{
  return x;
}
void increment()
{
  x = x + 1;
}

Patrón CQS thread safe.

private int x;
private int _x;
public int value()
{
  return x;
}
void increment()
{
  lock _x;   // por algún mecanismo
  _x = _x + 1;
  x = _x;
  unlock _x; // por algún mecanismo
}

Incluso en programas de un único hilo, a veces es mucho más conveniente tener un método que es una consulta combinada con comando. Martin Fowler cita el método pop() de una pila como un ejemplo.[3]

Véase también[editar]

Referencias[editar]

  1. Young, Greg. «CQRS Documents». Consultado el 8 de agosto de 2016. 
  2. Fowler, Martin. «CQRS». Consultado el 8 de agosto de 2016. 
  3. Fowler, Martin. «CommandQuerySeparation». Consultado el 8 de agosto de 2016. 

Otras lecturas[editar]

Enlaces externos[editar]