lunes, 19 de agosto de 2019

Pillándole el rollo a Command Query Responsibility Segregation (CQRS) de una vez por todas.

Hay que ver lo que se complica la gente con conceptos tan sencillotes (aunque increiblemente útiles). La ultima vez que hablé sobre CQRS con alguien; este alguien tenía un pifostio montado en la cabeza sobre event sourcing, read/write models, consistencia eventual y un buen montón de paranoias que creía que era en lo que consistía CQRS.


La realidad es que el concepto es muchísimo más sencillo que eso: CQRS es simplemente una idea que se desea honrar en la arquitectura (ya sea de software, de infraestructura, de contextualización, de comunicaciones, etc) de nuestro sistema. Esa idea es separar de forma muy explícita los componentes (de software, de infraestructura, etc) que gestionan un comando, con el potencial de provocar algún cambio de estado en el sistema, de los componentes que gestionan una consulta al sistema.

Y ya está. No es más que eso. Todo lo demás (ES, RW model, etc) son constuctos utilizados para honrar esa idea en diferentes capas del sistema (y para facilitar la extensión de CQRS a las subsiguientes capas) de una forma que nos permite sacarle todo el jugo a CQRS.

Repasemos un supuesto muy, pero que muy, básico:

En el código puro y duro; honrar a CQRS supone tener elementos y sus dependencias (no voy a decir clases porque no tiene por que ser OOP) muy claramente diferenciados para gestionar los comandos y las consultas. Aparte de las ventajas inherentes de esa arquitectura de software a nivel de programación; hacer esto nos permite extender CQRS al siguiente nivel.

Este siguiente nivel consiste en poder segregar las máquinas que ejecutan el código que gestiona los comandos y el que realiza las consultas. Si pensamos en los típicos servidores web; gracias a la arquitectura del paso anterior; podemos desplegar el código de gestión de comandos en un servidor (o en varios) y el código que realiza las consultas en otro (u otros). Aquí nos apoyamos en elementos como balanceadores, proxies inversos, servicios de descubrimiento, servidores de sesión y estado, etc para poder realizar la segregación y, de paso, ganar escalabilidad horizontal y redimiento.

En el último nivel (ya dije que el ejemplo iba a ser muy muy básico) tenemos la peristencia; la cual también podemos dividir entre la máquina que recibe los cambios a persistir producidos por un comando y la máquina que realiza las consultas del estado del sistema. Nos apoyamos en elementos como Read/Write model, Event Sourcing, etc para poder llevar a cabo esta segregación. La escalabilidad horizontal del Read Model es trivial y el rendimiento en un Read Model desnormalizado es muy alto.

Así que sí, como me pasó a mi una vez, alguien te pregunta alguna vez sobre las ventajas de CQRS así sin más; lo único que se puede responder, ante la falta de más contexto es: especialización y simplicidad; puesto que lo demás depende del contexto en el que se aplique. Si al entrevistador no le gusta la respuesta porque piensa que es insuficiente (si quiere más detalles tiene que darme contexto) o él mismo lo completa con cosas como escalabilidad, rendimiento, descentralización, etc; es que el propio entrevistador tiene una idea, quizás no equivocada, pero demasiado enrevesada, innecesaria y compleja; lo que significa que no tiene, de verdad, del todo claro la idea en sí y solo sabe de implementación de esa idea en todas las capas como un todo indivisible.

Esa visión es una versión un poco más avanzada de Mono-Lagarto que flipa un poco con buzzwords y al menos le echa algo de tiempo en leer sobre ellas.

Como decía mi abuela: "En el país de los Mono-Lagartos el buzzworder es el rey"

No hay comentarios:

Publicar un comentario