code design – Principio Command Query Separation – CQS

CQS
CQS

Introducción:

Command Query Separation (CQS), o en castellano separación de comandados y consultas, es un principio de diseño que fue acuñado por Bertrand Meyer en su libro Object Oriented Software Construction en el cual nos dice lo siguiente:

A method should either Change the State of an Object [the COMMAND], or Return a Result [the QUERY], but Not Both [the SEPARATION]

La idea principal detrás de este principio es que debemos dividir los métodos de un objeto en dos categorías, ya que al realizar una pregunta esta no debe cambiar la respuesta. Como resultado de aplicar este principio consistentemente ayuda a que los desarrolladores puedan entender mejor y más rápido el código.

Querys:

Retornan un resultado, responden una pregunta, pero no cambian el estado del sistema.

Commands:

Cambian el estado del sistema ejecutando una acción, pero no retornan ningún valor.

Aplicando CQS:

Antes

En esta clase tenemos dos métodos: EliminarCuenta y AgregarCuenta. Como se ve a continuación ambos métodos cambian el estado del sistema y devuelven resultados.

public class ServicioFinanciero
{
    public ListaCuenta EliminarCuenta(Cuenta cuenta)
    {
        repositorioCuenta.Delete(cuenta);
        repositorioCuenta.Save();

        return repositorioCuenta.
            Get(x => x.PersonaId.Equals(cuenta.PropietarioId)).ToList();
    }

    public Resultado AgregarCuenta(Cuenta cuenta)
    {
        if (string.IsNullOrEmpty(cuenta.Numero))
        {
            return Resultado.NumeroInvalido;
        }
        if (cuenta.PropietarioId == 0)
        {
            return Resultado.PropietarioInvalido;
        }

        repositorioCuenta.Add(cuenta);
        repositorioCuenta.Save();

        return Resultado.Exito;
    }
}
Después

Aplicando este principio ahora tenemos dos comandos: AgregarCuenta y EliminarCuenta y dos consultas: ValidarCuenta y ConsultarCuentas.

public class ServicioFinanciero
{
    public Resultado ValidarCuenta(Cuenta cuenta)
    {
        if (string.IsNullOrEmpty(cuenta.Numero))
        {
            return Resultado.NumeroInvalido;
        }
        return cuenta.PropietarioId == 0 ? 
           Resultado.PropietarioInvalido : 
           Resultado.Exito;
    }

    public void AgregarCuenta(Cuenta cuenta)
    {
        repositorioCuenta.Add(cuenta);
        repositorioCuenta.Save();
    }

    public void EliminarCuenta(Cuenta cuenta)
    {
        repositorioCuenta.Delete(cuenta);
        repositorioCuenta.Save();
    }

    public ListaCuenta ConsultarCuentas(Cuenta cuenta)
    {
        return repositorioCuenta
          .Get(x => x.PersonaId.Equals(cuenta.PropietarioId)).ToList();
    }
}

Cuando no aplicar CQS:

No es conveniente aplicar CQS en un escenario multihilo o reentrante, ya que la implementación se vuelve más difícil.

Antes
private static int contador = 0;
private readonly static object recurso = new object();
public static int Incrementar()
{
    lock (recurso) // por algún mecanismo
    {
        contador++;
        int copia= contador;
        return copia;
    }
}
Después
private static int contador = 0;
private readonly static object recurso = new object();
public static void Incrementar()
{
    lock (recurso) // por algún mecanismo
    {
        contador++;
    }
}

public static void Obtener()
{
    return contador;
}

Conclusiones: 

El principio Comman Query Separation (CQS), acuñado por Bertrand Meyer en su libro Object Oriented Software Construction,  señala que un método no puede realizar dos tareas a la vez, cambiar el estado del sistema (Command) y devolver un resultado (Query), para esto se debe dividir los métodos de un objeto en dos categorías. Pero debemos tener en cuenta que hay ciertos casos en donde es mejor no aplicar este principio para no volver más complejo el diseño.

Referencias:
Metal Tip:

Este artículo lo escribí escuchando la canción Dark roots of eart de la banda Testament de USA, les comparto el enlace.

Happy coding and Stay Heavy lml

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s