<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miguel Ángel Sánchez Chordi</title>
    <description>The latest articles on DEV Community by Miguel Ángel Sánchez Chordi (@mangelsnc).</description>
    <link>https://dev.to/mangelsnc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36581%2Ff8b0f997-ccda-4b3e-aad5-3f7a9f04494c.jpeg</url>
      <title>DEV Community: Miguel Ángel Sánchez Chordi</title>
      <link>https://dev.to/mangelsnc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mangelsnc"/>
    <language>en</language>
    <item>
      <title>API Gateway vs Load Balancer vs Reverse Proxy</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Wed, 03 Apr 2024 07:02:13 +0000</pubDate>
      <link>https://dev.to/mangelsnc/api-gateway-vs-load-balancer-vs-reverse-proxy-3ja5</link>
      <guid>https://dev.to/mangelsnc/api-gateway-vs-load-balancer-vs-reverse-proxy-3ja5</guid>
      <description>&lt;h4&gt;
  
  
  Infraestructuras de Gestión y Distribución de Tráfico
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Conoce las diferencias entre las distintas infraestructuras de gestión y distribución de tráfico
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/api-gateway-load-balancer-reverse-proxy/"&gt;&lt;strong&gt;Este post se publicó originalmente en el blog Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Escalado de aplicaciones web
&lt;/h3&gt;

&lt;p&gt;Con el paso del tiempo, las aplicaciones basadas en la web y los servicios que ofrecen han ido incrementado tanto en escala como en complejidad. Aunque era lo habitual años atrás, la idea de mantener un proyecto grande funcionando con un solo servidor es algo cada vez menos realista.&lt;/p&gt;

&lt;p&gt;Para manejar mayores volúmenes de tráfico tenemos dos formas diferentes de escalado: el escalado vertical y el escalado horizontal.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Escalado vertical&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Básicamente consiste en mejorar el hardware sobre el que corre nuestro proyecto, añadiendo más memoria, más CPU, más disco duro, más tarjetas de red… Antiguamente era la forma más barata de escalar y a día de hoy es una opción poco realista, ya que a medida que la demanda del servicio web aumenta, puede llegar un punto en el que el escalado vertical ya no sea suficiente para satisfacer las necesidades de rendimiento y disponibilidad del proyecto.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Escalado horizontal&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Consiste en agregar más servidores o instancias de manera distribuida para manejar la carga. Esto permite una mayor flexibilidad y capacidad para adaptarse a cambios en la demanda, así como una mayor tolerancia a fallos, ya que los servidores individuales pueden fallar sin degradar significativamente la disponibilidad del servicio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infraestructuras de Gestión y Distribución de Tráfico
&lt;/h3&gt;

&lt;p&gt;Es aquí, en las estrategias de escalado horizontal, donde juegan un papel importante las infraestructuras de gestión y distribución de tráfico, ya que gracias a ellas podemos controlar el flujo de datos y distribuir la carga de manera eficiente entre múltiples servidores o instancias, garantizando así un rendimiento óptimo y una alta disponibilidad del servicio.&lt;/p&gt;

&lt;p&gt;Vamos a ver tres de las más conocidas: &lt;em&gt;Reverse Proxy&lt;/em&gt; (Proxy inverso), &lt;em&gt;API Gateway&lt;/em&gt; (Puerta de acceso) y &lt;em&gt;Load Balancer&lt;/em&gt; (balanceador de carga).&lt;/p&gt;

&lt;p&gt;Si no te has visto en la necesidad de utilizarlas, es posible que tengas dudas sobre qué hace cada una de ellas o en qué se diferencian, así que vamos a ver las características y usos de cada una de ellas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reverse Proxy
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kKoSjjgH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ASL0APGCkDd8-0rsxVfZtXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kKoSjjgH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ASL0APGCkDd8-0rsxVfZtXQ.png" alt="" width="800" height="193"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;La función principal del reverse proxy es enmascarar la dirección real de un servidor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Empezamos por el más simple de los tres, el &lt;em&gt;reverse proxy&lt;/em&gt; o proxy inverso.&lt;/p&gt;

&lt;p&gt;El &lt;em&gt;reverse proxy&lt;/em&gt; básicamente es un servidor que actúa como intermediario entre los clientes y el o los servidores de destino. En lugar de establecerse una comunicación directa en cliente y servidor, el cliente conecta con el &lt;em&gt;reverse proxy&lt;/em&gt; y este se encarga de pasar la petición al servidor y devolver la respuesta correspondiente a los clientes.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Con qué propósito usamos un &lt;em&gt;reverse proxy?&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad.&lt;/strong&gt; Actúa como una barrera entre los clientes y los servidores de destino, ocultando la estructura interna de la red y proporcionando una capa adicional de seguridad contra ataques maliciosos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cacheo de contenido estático.&lt;/strong&gt; Almacena en caché el contenido estático como imágenes, archivos CSS y JavaScript para reducir la carga en los servidores de origen y mejorar los tiempos de carga de la página.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminación SSL/TLS.&lt;/strong&gt; Gestiona las conexiones SSL/TLS de los clientes y las termina en el proxy antes de reenviar las solicitudes a los servidores de destino, lo que simplifica la gestión de certificados SSL/TLS y mejora el rendimiento de los servidores. De esta forma la conexión HTTPS es únicamente entre el cliente y el proxy. Esto es especialmente útil cuando el &lt;em&gt;reverse proxy&lt;/em&gt; enmascara más de un servidor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balanceo de carga.&lt;/strong&gt; Sí, así es, el &lt;em&gt;reverse proxy&lt;/em&gt; se puede usar como balanceador de carga, ya que distribuye el tráfico entrante entre varios servidores de destino para mejorar la escalabilidad y la disponibilidad del servicio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La función de proxy inverso la realizan la mayoría de servidores web comerciales, como &lt;a href="https://www.nginx.com/"&gt;NGINX&lt;/a&gt;, &lt;a href="https://httpd.apache.org/"&gt;Apache&lt;/a&gt; y &lt;a href="https://learn.microsoft.com/es-es/iis/get-started/introduction-to-iis/iis-web-server-overview"&gt;Microsoft IIS&lt;/a&gt;, y también software específico como &lt;a href="https://www.haproxy.org/"&gt;HAProxy&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Balancer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IMtM_056--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AuogqnCQnaeIzPwzqyew6KQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IMtM_056--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AuogqnCQnaeIzPwzqyew6KQ.png" alt="" width="800" height="547"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Un balanceador de carga reparte el tráfico entre distintas instancias o servidores de un mismo servicio&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Un balanceador de carga (o &lt;em&gt;Load Balancer&lt;/em&gt; en inglés) es un dispositivo o software que distribuye el tráfico de red entrante entre múltiples servidores, con el objetivo de mejorar el rendimiento, la disponibilidad y la fiabilidad de una aplicación o servicio web.&lt;/p&gt;

&lt;p&gt;Al igual que en el caso del &lt;em&gt;reverse proxy&lt;/em&gt;, actúa como un intermediario entre el cliente y (en este caso) los servidores, ya que no es solo uno sino varios los servidores que oculta el &lt;em&gt;load balancer.&lt;/em&gt; Al ser varios servidores, se paralelizan las peticiones y se puede manejar un flujo de peticiones mucho mayor&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Con qué propósito usamos un balanceador de carga_?_&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distribución de carga.&lt;/strong&gt; Distribuye el tráfico de red entre varios servidores para evitar la sobrecarga de uno solo y garantizar un uso equitativo de los recursos disponibles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora del rendimiento.&lt;/strong&gt; Al distribuir la carga de trabajo entre múltiples servidores, un balanceador de carga puede mejorar el tiempo de respuesta y el rendimiento general de una aplicación o servicio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alta disponibilidad.&lt;/strong&gt; Si un servidor falla, el balanceador de carga puede redirigir automáticamente el tráfico a servidores alternativos que estén funcionando correctamente, lo que garantiza la disponibilidad continua del servicio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidad.&lt;/strong&gt; Facilita la adición o eliminación dinámica de servidores según las necesidades de carga, lo que permite escalar horizontalmente la infraestructura de manera flexible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Cómo reparte la carga un balanceador?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Dependiendo de su implementación, puede utilizar algoritmos de balanceo de carga simples, como round-robin (cada solicitud se envía a los servidores en secuencia) o algoritmos más avanzados que consideran la carga actual de los servidores, la latencia, entre otros factores.&lt;/p&gt;

&lt;p&gt;Los algoritmos de distribución de carga más habituales incluyen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Round Robin.&lt;/strong&gt; Este algoritmo distribuye las solicitudes de manera uniforme entre los servidores en secuencia. Cada solicitud se envía al siguiente servidor en la lista, y cuando se alcanza el último servidor, se vuelve al principio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Least Connections&lt;/em&gt; (Menos Conexiones).&lt;/strong&gt; Este algoritmo dirige las nuevas solicitudes al servidor con la menor cantidad de conexiones activas en ese momento. Es útil para distribuir la carga de manera más equitativa, considerando la carga real de cada servidor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Least Response Time&lt;/em&gt; (Menor Tiempo de Respuesta).&lt;/strong&gt; Similar al algoritmo de Menos Conexiones, este enfoque dirige las solicitudes al servidor que tiene el menor tiempo de respuesta en ese momento. Ayuda a maximizar la capacidad de respuesta y el rendimiento general del sistema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;IP Hashing&lt;/em&gt; (Hashing de IP).&lt;/strong&gt; Este algoritmo utiliza la dirección IP del cliente para determinar a qué servidor enviar la solicitud. De esta manera, todas las solicitudes de un cliente particular se envían siempre al mismo servidor, lo que puede ser útil para mantener la sesión de un usuario en un servidor específico.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Weighted Round Robin&lt;/em&gt; (Round Robin Ponderado).&lt;/strong&gt; Este algoritmo asigna un peso a cada servidor en función de su capacidad de procesamiento, y luego distribuye las solicitudes en función de esos pesos. Los servidores con mayor capacidad recibirán una mayor proporción de solicitudes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Random&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;(Aleatorio).&lt;/strong&gt; Este algoritmo elige aleatoriamente un servidor para manejar cada solicitud entrante. Aunque simple, puede no ser la opción más eficiente en términos de distribución de carga equitativa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cómo manejamos las sesiones con un balanceador de carga?
&lt;/h4&gt;

&lt;p&gt;Si el servicio que estamos enmascarando con nuestro balanceador requiere de una sesión, corremos el peligro de que en las siguientes peticiones un mismo cliente sea redirigido a otro servidor que no tenga su sesión guardada, y esto puede producir cierto malestar en el usuario al estar constantemente pidiéndole iniciar sesión de nuevo.&lt;/p&gt;

&lt;p&gt;Para ello, los balanceadores de carga cuentan con una característica conocida como &lt;strong&gt;&lt;em&gt;sticky bit&lt;/em&gt;&lt;/strong&gt; , que permite que las solicitudes de un cliente se dirijan siempre al mismo servidor durante la duración de una sesión específica, es decir, garantiza la persistencia de sesión al asociar un cliente con un servidor particular.&lt;/p&gt;

&lt;p&gt;Cuando se habilita el &lt;em&gt;sticky bit&lt;/em&gt;, el balanceador de carga utiliza una técnica, como el &lt;em&gt;hashing&lt;/em&gt; de la dirección IP del cliente o la inserción de una &lt;em&gt;cookie&lt;/em&gt; en el navegador del cliente, para identificar y asociar al cliente con un servidor específico. Como resultado, todas las solicitudes posteriores de ese cliente durante la misma sesión se redirigen al mismo servidor, lo que asegura una experiencia coherente para el usuario y permite que las sesiones persistan correctamente a través de múltiples solicitudes.&lt;/p&gt;

&lt;p&gt;Podemos encontrar implementaciones de balanceadores de carga en las principales plataformas &lt;em&gt;cloud&lt;/em&gt;, como &lt;a href="https://aws.amazon.com/es/elasticloadbalancing/"&gt;&lt;em&gt;AWS Elastic Load Balancer (ELB)&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://azure.microsoft.com/es-es/products/load-balancer/"&gt;&lt;em&gt;Microsoft Azure Load Balancer&lt;/em&gt;&lt;/a&gt; y &lt;a href="https://cloud.google.com/load-balancing?hl=es"&gt;&lt;em&gt;Cloud Load Balancing&lt;/em&gt;&lt;/a&gt; de Google.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Gateway
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s5scs-_h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ACup6l2mVRlAUNqMZE9a18g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s5scs-_h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ACup6l2mVRlAUNqMZE9a18g.png" alt="" width="800" height="547"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Un API Gateway sirve como punto de entrada único a una serie de servicios distribuidos e independientes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Por último, un &lt;em&gt;API Gateway&lt;/em&gt; es un componente de software que actúa como punto de entrada único (&lt;em&gt;single entry point&lt;/em&gt;) para una variedad de servicios y APIs dentro de una arquitectura de microservicios o de servicios distribuidos. Funciona como una capa intermedia entre clientes y múltiples servicios, proporcionando una interfaz unificada y facilitando la gestión, seguridad, supervisión y orquestación de las solicitudes y respuestas entre ellos.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cómo funciona un API Gateway?
&lt;/h4&gt;

&lt;p&gt;El funcionamiento de un API Gateway ya es algo más complejo que los casos anteriores. De base podemos entender sus similitudes con el balanceador de carga, pero con un matiz muy importante: tras un &lt;em&gt;API Gateway&lt;/em&gt; hay distintos servicio y que además pueden funcionar con diferentes protocolos. De hecho, un &lt;em&gt;API Gateway&lt;/em&gt; puede estar encubriendo un servicio que usa internamente un balanceador de carga para repartir la carga del servicio entre distintas instancias o servidores (hablamos por supuesto de magnitudes de tráfico enormes).&lt;/p&gt;

&lt;p&gt;Veamos los pasos básicos de su funcionamiento:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recepción de solicitudes.&lt;/strong&gt; El &lt;em&gt;API Gateway&lt;/em&gt; recibe las solicitudes de los clientes y las enruta a los servicios correspondientes basándose en reglas de enrutamiento configuradas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traducción de protocolos.&lt;/strong&gt; Puede traducir los protocolos de comunicación, por ejemplo, convirtiendo solicitudes HTTP en llamadas a servicios internos usando protocolos como &lt;em&gt;gRPC&lt;/em&gt; o &lt;em&gt;Thrift&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autenticación y autorización.&lt;/strong&gt; Gestiona la autenticación y la autorización de los clientes, verificando las credenciales y aplicando políticas de acceso antes de enviar las solicitudes a los servicios subyacentes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agregación de datos.&lt;/strong&gt; Puede combinar múltiples llamadas a servicios internos para formar una única respuesta para el cliente, reduciendo así la latencia y el tráfico de red.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitorización y análisis.&lt;/strong&gt; Recopila métricas y registros de las solicitudes y respuestas para facilitar la supervisión, el análisis de rendimiento y la solución de problemas.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Con qué propósito usamos un balanceador de carga?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unificación de interfaces.&lt;/strong&gt; Proporciona una única interfaz para los clientes, simplificando su interacción con un conjunto diverso de servicios internos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gestión de versiones.&lt;/strong&gt; Permite la introducción y el control de versiones de APIs, lo que facilita la evolución de los servicios subyacentes sin afectar a los clientes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad centralizada.&lt;/strong&gt; Implementa políticas de seguridad centralizadas, como autenticación, autorización y cifrado, para todos los servicios internos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orquestación y transformación.&lt;/strong&gt; Permite la orquestación de solicitudes a través de múltiples servicios internos y la transformación de datos según sea necesario.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidad y disponibilidad.&lt;/strong&gt; Puede distribuir la carga de manera equitativa entre múltiples instancias de servicios internos, mejorando así la escalabilidad y la disponibilidad del sistema.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Problemas comunes
&lt;/h4&gt;

&lt;p&gt;Una infraestructura tan compleja no está exenta de problemas, veamos cuales son los más comunes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cuellos de botella de rendimiento.&lt;/strong&gt; Un &lt;em&gt;API Gateway&lt;/em&gt; puede convertirse en un cuello de botella si no se dimensiona adecuadamente para manejar la carga de solicitudes entrantes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complejidad de configuración.&lt;/strong&gt; Configurar y mantener reglas de enrutamiento, políticas de seguridad y transformaciones de datos puede volverse complejo a medida que aumenta la cantidad de servicios y funcionalidades implementadas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puntos únicos de fallo.&lt;/strong&gt; Si un &lt;em&gt;API Gateway&lt;/em&gt; es el único punto de entrada para todos los servicios, un fallo en él puede afectar la disponibilidad de todo el sistema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sobrecarga de red&lt;/strong&gt; : El enrutamiento de todas las solicitudes a través del &lt;em&gt;API Gateway&lt;/em&gt; puede introducir una sobrecarga adicional en la red, especialmente en entornos distribuidos a gran escala.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;De nuevo, podemos encontrar implementaciones de &lt;em&gt;API Gateway&lt;/em&gt; en los principales proveedores de &lt;em&gt;cloud&lt;/em&gt; como &lt;a href="https://aws.amazon.com/es/api-gateway/"&gt;&lt;em&gt;AWS API Gateway&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://azure.microsoft.com/es-es/products/api-management"&gt;&lt;em&gt;Azure API Management&lt;/em&gt;&lt;/a&gt; o &lt;a href="https://cloud.google.com/apigee?hl=es"&gt;&lt;em&gt;Google Cloud API Gateway (Apigee)&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; así como soluciones Open Source como &lt;a href="https://konghq.com/products/kong-gateway"&gt;&lt;em&gt;Kong&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusiones
&lt;/h3&gt;

&lt;p&gt;Como hemos podido ver, aunque similares en su propósito, estas tres infraestructuras de gestión y distribución de tráfico tienen usos muy distintos y trabajan de formas muy diferentes.&lt;/p&gt;

&lt;p&gt;Es importante saber elegir en cada caso cuál necesitamos, ya que elegir mal puede derivar en añadir un extra de complejidad a nuestro proyecto, además de salirnos caro el error (económicamente hablando).&lt;/p&gt;

&lt;p&gt;Recordad, empezad siempre por lo mínimo necesario, siempre habrá tiempo de escalar más alto!&lt;/p&gt;




</description>
      <category>reverseproxy</category>
      <category>microservices</category>
      <category>distributedsystems</category>
      <category>apigateway</category>
    </item>
    <item>
      <title>Vertical Slices 101</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Sun, 25 Feb 2024 10:02:08 +0000</pubDate>
      <link>https://dev.to/mangelsnc/vertical-slices-101-emi</link>
      <guid>https://dev.to/mangelsnc/vertical-slices-101-emi</guid>
      <description>&lt;h4&gt;
  
  
  Clean Architectures
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Todo lo que necesitas saber sobre Vertical Slices
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xH8JDBtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AADcTTPffhMFBTBjfivlynw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xH8JDBtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AADcTTPffhMFBTBjfivlynw.png" alt="" width="800" height="845"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Vertical Slices sobre el modelo tradicional de capas&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/vertical-slices-101/"&gt;&lt;strong&gt;Artículo publicado originalmente en blog Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿De dónde viene el patrón Vertical Slices?
&lt;/h3&gt;

&lt;p&gt;Tras haber hablado durante un tiempo de distintos modelos de &lt;a href="https://secture.com/blog/clean-architectures-arquitecturas-limpias/"&gt;Clean Architectures&lt;/a&gt;, me gustaría introducir un patrón que discute su eficacia, o al menos sus ventajas a corto/medio plazo.&lt;/p&gt;

&lt;p&gt;El patrón &lt;em&gt;Vertical Slices&lt;/em&gt; fue creado por &lt;a href="https://www.jimmybogard.com/vertical-slice-architecture/"&gt;Jimmy Bogard&lt;/a&gt; como una respuesta a las ya tradicionales arquitecturas limpias (&lt;a href="https://secture.com/blog/arquitectura-hexagonal-101/"&gt;Hexagonal o Ports&amp;amp;Adapters&lt;/a&gt;, &lt;a href="https://secture.com/blog/onion-architecture-101/"&gt;Onion&lt;/a&gt;, &lt;a href="https://secture.com/blog/screaming-architecture/"&gt;Screaming&lt;/a&gt;…)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Clean Architecture&lt;/em&gt; (siempre según Jimmy), te obliga a seguir una serie de reglas de dependencia que implican crear muchas abstracciones a cambio de muy poco beneficio, ya que el principal objetivo de &lt;em&gt;Clean Architecture&lt;/em&gt; es eliminar la dependencia de cualquier &lt;em&gt;framework&lt;/em&gt; o librería de terceros.&lt;/p&gt;

&lt;p&gt;El beneficio real de estas abstracciones y reglas es difícilmente apreciable, ya que nunca se ha dado el caso de tener que cambiar de Framework o de base de datos (excepto quizá al ejecutar baterías de tests). Pero seguir reglas por seguirlas no va con Jimmy (ni con nadie, supongo), así que propuso su propio modelo de arquitectura.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es el patrón Vertical Slices?
&lt;/h3&gt;

&lt;p&gt;Con un patrón de &lt;em&gt;Clean Architecture&lt;/em&gt; hacemos una separación por capas, habitualmente &lt;em&gt;Infrastructure&lt;/em&gt; (adaptadores de librerías de terceros), &lt;em&gt;Application&lt;/em&gt; (lógica de negocio) y &lt;em&gt;Domain&lt;/em&gt; (abstracciones y contratos).&lt;/p&gt;

&lt;p&gt;La propuesta de Jimmy pasa por, en lugar de dividir nuestro código en capas por cuestiones técnicas, dividirlo por funcionalidad. Cada funcionalidad será una &lt;em&gt;slice&lt;/em&gt; y agrupará todas estas capas. De este modo, cada funcionalidad es una caso de uso distinto con distintas necesidades que se abordarán de la forma mas adecuada.&lt;/p&gt;

&lt;p&gt;Podría entenderse como un modulo independiente dentro del proyecto, que controla desde la &lt;em&gt;request&lt;/em&gt; hasta la &lt;em&gt;response&lt;/em&gt; de forma independiente (esto, inevitablemente nos lleva a pensar en &lt;a href="https://secture.com/blog/command-query-responsibility-segregation-cqrs/"&gt;CQRS&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w1KHBNHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/581/1%2Aes3HWrY3QytuXG0sj2H_tA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w1KHBNHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/581/1%2Aes3HWrY3QytuXG0sj2H_tA.png" alt="" width="581" height="379"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Esquema original de Vertical Slices Architecture. Créditos a Jimmy Bogard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;La esencia de &lt;em&gt;Vertical Slices Architecture&lt;/em&gt; radica en minimizar el acoplamiento entre &lt;em&gt;slices,&lt;/em&gt; maximizando a su vez el acoplamiento en cada &lt;em&gt;slice&lt;/em&gt; (ejes de cambio).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When adding or changing a feature in an application, I’m typically touching many different “layers” in an application. I’m changing the user interface, adding fields to models, modifying validation, and so on. Instead of coupling across a layer, we couple vertically along a slice. &lt;strong&gt;Minimize coupling between slices, and maximize coupling in a slice.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con este enfoque las capas compartidas desaparecen y las abstracciones se vuelven innecesarias, cada &lt;em&gt;slice&lt;/em&gt; implemente únicamente aquello que necesita, y cada &lt;em&gt;slice&lt;/em&gt; decide cómo manejar la &lt;em&gt;request&lt;/em&gt; que tiene asignada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dLUePVhw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/917/1%2A1xrZZrq2i7Z8Mt20uW5kLQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dLUePVhw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/917/1%2A1xrZZrq2i7Z8Mt20uW5kLQ.png" alt="" width="800" height="244"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Créditos a Jimmy Bogard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Los &lt;a href="https://martinfowler.com/eaaCatalog/"&gt;&lt;em&gt;Domain Logic Patterns&lt;/em&gt;&lt;/a&gt; de Martin Fowler ya no son una decisión que abarque todo el proyecto, sino que cada &lt;em&gt;slice&lt;/em&gt; se autogestiona y decide cuales usar y cuando hacerlo. Esto favorece empezar cualquier &lt;em&gt;slice&lt;/em&gt; de la forma más sencilla posible e ir refactorizando a patrones a medida que sea necesario, a su debido tiempo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Desventajas
&lt;/h3&gt;

&lt;p&gt;El propio Jimmy Reconoce que este patrón no es para todos los equipos, ya que estos deben de tener cierta madureza y experiencia en detectar &lt;em&gt;code smells&lt;/em&gt; y en aplicar refactors siguiendo las clásicas técnicas del libro &lt;a href="https://amzn.to/3SMa0gW"&gt;Refactoring to Patterns de Joshua Kerievsky&lt;/a&gt;, moviendo lógica compleja a una capa de dominio compartido (siempre y cuando sea realmente necesario)&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Leer sobre un patrón que contradice una tendencia al alza como las &lt;em&gt;Clean Architectures&lt;/em&gt; siempre resulta sumamente interesante, ya que podemos reflexionar sobre lo que estamos haciendo y por qué lo estamos haciendo (seguimos reglas por seguirlas?).&lt;/p&gt;

&lt;p&gt;No obstante, en mi opinión este patrón favorece la falta de coherencia entre las distintas funcionalidades de un proyecto, haciendo que tengas que aprender de nuevo en cada una que vayas a tocar cómo está diseñada o implementada.&lt;/p&gt;

&lt;p&gt;Puede que sea un enfoque idóneo en proyectos muy grandes con equipos claramente definidos y con formas de trabajar o necesidades claramente distintas, algo así como aplicar microservicios a nivel monolítico, pero creo que en proyectos más pequeños o con una rotación frecuente entre quién va a trabajar en qué funcionalidad, contribuye más al caos.&lt;/p&gt;

&lt;p&gt;Si que me parece un ejercicio interesante desde el punto de vista de que, al pasar por distintas funcionalidades con distintas implementaciones, podemos detectar qué patrones o técnicas están siendo provechosas en otras &lt;em&gt;slices&lt;/em&gt; y ver de incorporarlas a otras, eliminando así los patrones implementados solo porque han sido útiles en otra parte de la aplicación. No obstante, me parece un proceso largo que puede tener sentido trabajando en empresas de producto, pero poco favorable cuando trabajamos en proyectos más cortos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Referencias
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jbogard/presentations/tree/master/VerticalSliceArchitectures"&gt;Presentación de Vertical Slices Architecture&lt;/a&gt; (Jimmy Bogard)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=SUiWfhAhgQw"&gt;Conferencia de Vertical Slices Architecture&lt;/a&gt;(Jimmy Bogard)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jimmybogard.com/vertical-slice-architecture/"&gt;Artículo original de Vertical Slices Architecture&lt;/a&gt; (Jimmy Bogard)&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>cleancode</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>¿Cómo trabajar correctamente con fechas?</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Wed, 14 Feb 2024 07:03:16 +0000</pubDate>
      <link>https://dev.to/mangelsnc/como-trabajar-correctamente-con-fechas-4n3l</link>
      <guid>https://dev.to/mangelsnc/como-trabajar-correctamente-con-fechas-4n3l</guid>
      <description>&lt;h4&gt;
  
  
  Aprende a manejar fechas en proyectos internacionales
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_eL8C6g6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AxsvRdrhuvx79LZdfZnGDmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_eL8C6g6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AxsvRdrhuvx79LZdfZnGDmg.png" alt="" width="800" height="431"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Mapa de zonas horarias del mundo. Créditos: Wikipedia.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/como-trabajar-correcteamente-con-fechas/"&gt;&lt;strong&gt;Artículo originalmente publicado en Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Las fechas son una de las grandes olvidadas en los planteamientos iniciales de un proyecto y esto puede tener repercusión en el mantenimiento a medio largo/plazo. Inicialmente, cuando arrancamos un proyecto simplemente guardamos la fecha y la hora sin preocuparnos demasiado al respecto, pero luego proyecto crece, requiere una adaptación para el mercado internacional (&lt;em&gt;internacionalización&lt;/em&gt;) y centramos todo el foco en las traducción y la localización de nuestro sitio web.&lt;/p&gt;

&lt;p&gt;Pero, ¿acaso es la misma hora en todos los países? ¿Acaso en España no cambiamos la hora dos veces al año?&lt;/p&gt;

&lt;p&gt;Aunque parezca poco importante, puede provocar auténticos desastres administrativos a nuestro proyecto, como, por ejemplo, publicar un producto en otro país 6h antes de lo esperado, o que tareas programadas se ejecuten una hora antes o después de lo necesario debido al cambio de hora.&lt;/p&gt;

&lt;p&gt;¿Cómo manejamos todo esto?&lt;/p&gt;

&lt;h3&gt;
  
  
  Zonas Horarias
&lt;/h3&gt;

&lt;p&gt;En realidad el sistema horario internacional es algo que todos conocemos y que todos los lenguajes de programación de alto nivel que implementan fechas tienen incorporado a su API, por lo que abordar este problema solo requiere de un poco de planificación, consenso y disciplina.&lt;/p&gt;

&lt;p&gt;Cuando generamos una fecha con nuestro lenguaje preferido, este, generalmente, lo hará utilizando la zona horaria configurada. Esta configuración puede tener distintos orígenes y prioridades. Veamos algunos ejemplos ordenados de más prioritarios a menos prioritarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configuración en &lt;em&gt;runtime (en tiempo de ejecución)&lt;/em&gt;&lt;/strong&gt;: acabamos de configurar el lenguaje para que use una zona por defecto&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuración del &lt;em&gt;framework&lt;/em&gt; o librería de fechas&lt;/strong&gt; : &lt;strong&gt;a&lt;/strong&gt; lgunos &lt;em&gt;frameworks&lt;/em&gt; te permiten ajustar este parámetro para que en todo el proyecto se use la misma configuración (a no ser que se sobreescriba en runtime).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archivos de configuración&lt;/strong&gt; : los lenguajes interpretados suelen dejarnos ajustar algunos parámetros del intérprete en archivos del sistema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuración del sistema operativo&lt;/strong&gt; : &lt;strong&gt;s&lt;/strong&gt; i ninguna de las anteriores ha sido configurada, por defecto usará la del sistema.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;️&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Pro Tip:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;atención con la configuración de la zona horaria de la base de datos, ya que si permitimos que el motor de la base de datos asigne fechas automáticamente, este lo hará siguiendo su propia configuración, que no tiene por qué ser la misma que la del lenguaje o _runtime&lt;/em&gt;._&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Coordinated Universal Time (UTC)
&lt;/h3&gt;

&lt;p&gt;Hay una zona horaria especial que nos permite controlar a la perfección estas diferencias entre las distintas zonas horarias, y es la zona UTC &lt;em&gt;(Coordinated Universal Time).&lt;/em&gt; Esta zona es la “zona cero”, es decir, no tiene desplazamiento horario, podríamos llamarlo la hora central del planeta. En otros contextos se le conoce como GMT &lt;em&gt;(Greenwich Median Time),&lt;/em&gt; aunque UTC es el reemplazo oficial de GMT. En argot militar también se le conoce como &lt;em&gt;Hora Zulú,&lt;/em&gt; y permite coordinar operaciones usando una hora común.&lt;/p&gt;

&lt;p&gt;Si guardamos todas nuestras fechas en zona UTC, podremos calcular muy sencillamente la fecha en cualquier zona del mundo. De hecho, ni siquiera tendremos que hacer los cálculos, ya que es una función muy común en cualquier librería de fechas o incluso en las APIs propias de los lenguajes de programación. Veamos un ejemplo en PHP:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RGRWu54K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A6wk5QwzFNUMJRz2v4iyq5Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RGRWu54K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A6wk5QwzFNUMJRz2v4iyq5Q.png" alt="" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En este caso he optado por configurar la zona por defecto en &lt;em&gt;runtime&lt;/em&gt;, solo para ejemplificar su uso.&lt;/p&gt;

&lt;p&gt;Lo interesante de este uso es que el &lt;em&gt;frontend&lt;/em&gt; puede determinar la zona horaria del usuario por distintos métodos (dominio, IP, selección manual del usuario…) y mostrar las fechas que vienen del &lt;em&gt;backend&lt;/em&gt; ajustadas a la zona horaria del usuario, sin errores, sin problemas derivados por el horario de verano… etc. Y, simultáneamente, el tiempo de todas nuestras operaciones queda coordinado por una hora única en el &lt;em&gt;backend.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Formatos de fecha
&lt;/h3&gt;

&lt;p&gt;El cómo queramos mostrar la fecha a los usuarios ya es un asunto más personal o cultural, en base a los diferente países a los que vayamos a mostrar las fechas. Vamos a ver algunos de los ejemplos más recurrentes:&lt;/p&gt;

&lt;h4&gt;
  
  
  Formato francés
&lt;/h4&gt;

&lt;p&gt;Es el más extendido en Europa, consiste en una ordenación de día, mes y año, en ese orden. Por ejemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;13/12/1989&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;13-12-1989&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Da igual el uso de barras, guiones… lo importante es el orden. En caso de mostrar la hora, esta se muestra a continuación separada por un espacio en blanco, con la ordenación hora, minutos, segundos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;13/12/1989 11:24:26&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Formato americano
&lt;/h4&gt;

&lt;p&gt;Es el más extendido en America. Consiste en una ordenación de mes, día y año, en ese orden. Por ejemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;12/13/1989&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;12–13–1989&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Da igual el uso de barras, guiones… lo importante es el orden. En caso de mostrar la hora, esta se muestra a continuación separada por un espacio en blanco, con la ordenación hora, minutos, segundos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;13/12/1989 11:24:26&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Estándar ISO-8601
&lt;/h4&gt;

&lt;p&gt;Se sigue el criterio de especificar en orden primeramente los períodos de tiempo más largos y posteriormente los más cortos. Así, para especificar una fecha primero se escribe el año, posteriormente el mes y a continuación el día.&lt;/p&gt;

&lt;p&gt;Por ejemplo, para especificar la fecha 13 de diciembre de 1989 del ejemplo anterior, el resultado sería:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1989–12–13&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En el caso de incluir la hora también esta estaría acotada por las letras “T” y “Z”, por ejemplo, si la hora fuesen las 11:26:24am, usaríamos la notación:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1989–12–13T11:26:24Z&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este formato es especialmente útil para realizar ordenaciones eficientes y para comunicar fechas entre distintos sistemas, ya que es un estándar bien conocido y cualquier lenguaje implementa el soporte para esta notación.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusiones
&lt;/h3&gt;

&lt;p&gt;Es conveniente que adoptemos esta práctica de forma habitual, ya que cuando un proyecto escala a nivel internacional, es más difícil realizar la adaptación, ya que tendremos millones de registros en base de datos con la zona horaria equivocada, y cientos de lineas de código que cambiar debido a que no tienen en cuenta la zona horaria.&lt;/p&gt;

&lt;p&gt;Puede parecer más cómodo empezar sin tenerlo en cuenta, ya que la fecha que le pasemos al &lt;em&gt;frontend&lt;/em&gt; es la que tiene que mostrar, sin conversiones ni nada que impida avanzar de forma rápida y sin engorros, pero como se suele decir: &lt;em&gt;es pan para hoy y hambre para mañana&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Añadir esta práctica va a aportar mucho control a nuestras operaciones coordinadas y al crecimiento a medio/largo plazo de nuestro proyecto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bibliografía
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/timezones.others.php"&gt;&lt;strong&gt;Zonas Horarias.&lt;/strong&gt; PHP.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://es.wikipedia.org/wiki/ISO_8601"&gt;&lt;strong&gt;ISO-8601.&lt;/strong&gt; Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>softwareengineering</category>
      <category>scalingsoftwareprodu</category>
      <category>timezone</category>
      <category>goodpractices</category>
    </item>
    <item>
      <title>Screaming Architecture</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Thu, 01 Feb 2024 08:00:27 +0000</pubDate>
      <link>https://dev.to/mangelsnc/screaming-architecture-g7o</link>
      <guid>https://dev.to/mangelsnc/screaming-architecture-g7o</guid>
      <description>&lt;h4&gt;
  
  
  Clean Architectures
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Arquitecturas que gritan su propósito
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LiOjNeWi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AOwRfnO-g7DJBGqkkEMOm7g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LiOjNeWi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AOwRfnO-g7DJBGqkkEMOm7g.jpeg" alt="" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/screaming-architecture/"&gt;&lt;strong&gt;Este artículo se publicó originalmente en el blog Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducción
&lt;/h3&gt;

&lt;p&gt;Cuántas veces has abierto un proyecto y has pensado: &lt;em&gt;Laravel&lt;/em&gt;, &lt;em&gt;Symfony&lt;/em&gt;, &lt;em&gt;Django&lt;/em&gt;, &lt;em&gt;Rails&lt;/em&gt;, &lt;em&gt;NestJS&lt;/em&gt;, &lt;em&gt;Wordpress&lt;/em&gt;…? Y por contra, cuántas veces has abierto un proyecto y has pensado: aplicación de podcast, sistema de venta de tickets, plataforma de alquileres, red social…?&lt;/p&gt;

&lt;p&gt;Es bastante común en nuestro mundillo dejarnos llevar por las decisiones que han tomado otros, y por otros me refiero a a los desarrolladores del framework de turno que estemos usando. Arrancamos un proyecto con un framework y directamente nos dejamos llevar por la estructura de directorios y decisiones de arquitectura que más le convenían al equipo que ha desarrollado el framework, en lugar de centrarnos en qué necesita nuestro proyecto para &lt;em&gt;gritar&lt;/em&gt; su propósito.&lt;/p&gt;

&lt;h3&gt;
  
  
  Screaming Architectures
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html"&gt;En 2011, Bob Martin proponía el concepto de &lt;em&gt;screaming architecture&lt;/em&gt;&lt;/a&gt;: arquitecturas que &lt;em&gt;gritan&lt;/em&gt; a los cuatro vientos su propósito, el proyecto que modelan, vaya.&lt;/p&gt;

&lt;p&gt;El símil más sencillo de entender es el de los planos de un arquitecto: de un solo vistazo se entiende si el diseño corresponde a una casa, un aeropuerto, una plaza, un centro comercial, etc. En ningún momento se habla de materiales. No aún, esos detalles vendrán después. La meta es definir un diseño que cumpla con la especificación del proyecto: un hogar acogedor, un aeropuerto eficiente, una plaza con sombras y bancos, un centro comercial accesible a todo el mundo…&lt;/p&gt;

&lt;p&gt;En el campo del desarrollo una buen arquitectura debería de cumplir esos mismos objetivos, ajustarse al sistema que se está modelando, sin importar si la base de datos es MySQL o MongoDB, si usaremos &lt;em&gt;Laravel&lt;/em&gt; o &lt;em&gt;Symfony&lt;/em&gt;, si usaremos ORMs basados en DataMapper o en ActiveRecord. Nuestra arquitectura debe de poder probarse (testarse) sin haber tomado aún esas decisiones.&lt;/p&gt;

&lt;h3&gt;
  
  
  El framework solo es una herramienta más
&lt;/h3&gt;

&lt;p&gt;A lo que nos lleva esto es a que debemos considerar el framework que hayamos elegido como una dependencia externa más, no la base sobre la que asentar nuestro dominio. No debemos de tomar las decisiones cruciales en base a las características o funcionalidades que tiene el framework que hayamos elegido, ya que estaremos atándonos a él.&lt;/p&gt;

&lt;p&gt;Puede ser tentador, y a todos nos ha pasado, pero ciertamente hay un mundo de ventajas cuando asumimos el control de nuestro dominio, y nos protege contra contratiempos inesperados: dependencias de terceros que se abandonan o que no se actualizan, giros en el diseño que nos afectan de tal manera que no podemos seguir trabajando a no ser que invirtamos tiempo en actualizar al nuevo diseño… etc&lt;/p&gt;

&lt;p&gt;Pero no todo es proponerse desacoplarse del framework de turno, tenemos que saber elegir bien nuestras herramientas, ya que muchos frameworks solo funcionan bien si sigues sus reglas y te acoplas a él, y ahí ya depende de nosotros saber si conviene meterse en ese berenjenal, o simplemente dejarse llevar, bien por la duración del proyecto, por las expectativas de crecimiento o simplemente porque es un MVP que desecharemos nada más validemos nuestro negocio.&lt;/p&gt;

&lt;p&gt;Si optas por desacoplarte, infórmate bien de tus opciones. Los frameworks que se definen a si mismos como &lt;em&gt;opinionated&lt;/em&gt; suelen marcar un modo de trabajo rígido del que es difícil escapar si queremos seguir sacándole partido, y muchas veces es mejor optar por &lt;em&gt;microframeworks&lt;/em&gt; que podamos ir ampliando con otras librerías de terceros o con las nuestras propias.&lt;/p&gt;

&lt;p&gt;Una buena forma de detectar si será complicado o no desacoplarse del framework, es detectar cuál es su componente principal. Si es un ORM, seguramente sea difícil abstraerse de él, ya que por diseño nos obliga a usar una base de datos, pero si su componente principal es un container de dependencias, ten por seguro que será sencillo, ya que te está dando la herramienta principal para conseguir ese desacople.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusiones
&lt;/h3&gt;

&lt;p&gt;S_creaming architecture_ es más un concepto que una arquitectura en si misma. La única regla que debe de cumplir es &lt;em&gt;gritar su propósito,&lt;/em&gt; no ceder el control a un framework, CMS o a una librería que acapare el protagonismo y empuje abajo nuestro dominio de negocio.&lt;/p&gt;

&lt;p&gt;No es una tarea sencilla. No siempre va a ser factible. No siempre va a ser rentable. ¿Es una mala idea? En absoluto. En mi experiencia tras haber podido trabajar en proyectos usando este enfoque, he visto que los tiempos de onboarding y adaptación de nuevos desarrolladores es mucho menor, en comparación.&lt;/p&gt;

&lt;p&gt;A veces surgen fricciones cuando un desarrollador del framework elegido se une al proyecto y las cosas no se hacen como él acostumbra a hacer, pero su comprensión del dominio es mucho mayor en menos tiempo, y aprender un nuevo &lt;em&gt;workflow&lt;/em&gt; es algo que hacemos cada poco tiempo.&lt;/p&gt;

&lt;p&gt;Por otra parte, ese control sobre el &lt;em&gt;workflow&lt;/em&gt; nos da un extra de independencia a la hora de tomar decisiones relevantes en el diseño de nuestro proyecto y la posibilidad de modificarlo según nuestras necesidades.&lt;/p&gt;

&lt;p&gt;En cambio, si el proyecto que afrontas tiene una duración finita, sin posibilidad de expandirse o de crecer, o de añadir más desarrolladores, no dudes en usar las herramientas que consideres para entregar a tiempo, acoplándote y sacándoles todo su jugo&lt;/p&gt;




</description>
      <category>screamingarchitectur</category>
      <category>cleancode</category>
      <category>cleanarchitecture</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Clean Architectures 101</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Thu, 30 Nov 2023 14:23:07 +0000</pubDate>
      <link>https://dev.to/mangelsnc/clean-architectures-101-1l12</link>
      <guid>https://dev.to/mangelsnc/clean-architectures-101-1l12</guid>
      <description>&lt;h4&gt;
  
  
  Arquitecturas Limpias
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Todo lo que necesitas saber sobre arquitecturas limpias
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_apHBZVJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/772/1%2AB7LkQDyDqLN3rRSrNYkETA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_apHBZVJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/772/1%2AB7LkQDyDqLN3rRSrNYkETA.jpeg" alt="" width="772" height="567"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Esquema de arquitectura limpia&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/clean-architectures-arquitecturas-limpias/"&gt;&lt;strong&gt;Post publicado originalmente en el blog Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Allá por el año 2012, Bob Martin acuñó el término de “Arquitectura Limpia” para referirse a aquellas arquitecturas de software que cumplen estos requisitos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Son independientes del framework&lt;/strong&gt;
La arquitectura no necesita que exista un framework por debajo para funcionar, nuestro código debería de poder portarse a otro framework y seguir funcionando. No quiere decir esto que nuestro código de infraestructura no requiera cambios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Son testables&lt;/strong&gt;
Las reglas de negocio de nuestro código deberían de ser testables (unitariamente al menos) sin depender de servidores web, bases de datos, interfaz de usuario o cualquier librería de terceros.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Son independientes de la capa de presentación (UI)&lt;/strong&gt;
La capa de presentación o &lt;em&gt;frontend&lt;/em&gt; debería de ser independiente del sistema, reemplazable y &lt;em&gt;multimedia,&lt;/em&gt; es decir, debería de poder ser un entorno web, un entorno de consola, una app móvil, otra API o cualquier otro sistema que podamos imaginar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Son independientes de la base de datos (DB)&lt;/strong&gt;
Deberíamos de poder cambiar de MySQL a PostgreSQL, MongoDB o cualquier otro &lt;em&gt;provider&lt;/em&gt; sin que esto afecte a nuestras reglas de negocio. No quiere decir esto que nuestro código de infraestructura no requiera cambios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Son independientes de cualquier dependencia externa (&lt;em&gt;third parties)&lt;/em&gt;&lt;/strong&gt;
Todo es reemplazable, ninguna dependencia debería de ser fuerte. ¿No nos convence nuestra librería de UUIDs? Reemplazarla debería de ser trivial. ¿Cambiamos de ORM? La lógica de negocio no debería de notarlo.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  La regla de dependencia
&lt;/h3&gt;

&lt;p&gt;Veamos una versión simplificada del esquema de arriba:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8vVE7w3b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AaHtPDc8wHJZxopJ52MajZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8vVE7w3b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AaHtPDc8wHJZxopJ52MajZA.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Esquema de arquitectura limpia simplificado&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cada uno de los círculos concéntricos representa una capa, y esta capa a su vez es una barrera que sólo puede ser atravesada por sus capas superiores. De este modo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infraestructura&lt;/strong&gt; puede acceder a &lt;strong&gt;Aplicación&lt;/strong&gt; y a  &lt;strong&gt;Dominio&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicación&lt;/strong&gt; puede acceder a  &lt;strong&gt;Dominio&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dominio&lt;/strong&gt; sólo puede acceder a  &lt;strong&gt;Dominio&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuanto más hacia dentro penetramos en las capas, más nos adentramos en la lógica de negocio, las reglas y las políticas. Cuanto más hacia fuera nos movemos, más cerca estamos de los agentes externos o mecanismos (clientes web o mobile, servicios externos o APIs, servicios de infraestructura como bases de datos, sistemas de colas, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Contenido de las capas
&lt;/h3&gt;

&lt;p&gt;Cada una de estas capas contiene distintos elementos de nuestro código, vamos a hacer un pequeño repaso al contenido de cada una de ellas:&lt;/p&gt;

&lt;h4&gt;
  
  
  Dominio
&lt;/h4&gt;

&lt;p&gt;Esta es la capa más cercana al negocio, por no decir que es el negocio en sí misma. En la capa de dominio es donde residen todas las piezas fundamentales que, además, servirán como lenguaje común para comunicarse entre las otras capas. Por ejemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entidades:&lt;/strong&gt; modelos de datos con identidad propia, compuestos por &lt;em&gt;Value Objects&lt;/em&gt;, que pueden ser anémicos o no.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value Objects:&lt;/strong&gt; piezas fundamentales para modelar entidades o agregados. Los &lt;em&gt;value objects&lt;/em&gt; representan elementos básicos de nuestro dominio, como pueden ser el &lt;em&gt;id&lt;/em&gt; de un usuario, su nombre, su correo… estas diminutas clases contienen la lógica de validación de sus valores, no tienen entidad propia y se comparan por valor, como una primitiva más.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Servicios:&lt;/strong&gt; son pequeñas clases que ejecutan una acción, como puede ser recuperar un usuario de la base de datos, construir la entidad y devolverla o devolver un &lt;em&gt;NullObject&lt;/em&gt; si no existe. Estos servicios se pueden usar solos o combinados en los distintos casos de uso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eventos:&lt;/strong&gt; los eventos de dominio son la forma más eficaz de comunicarse en dirección contraria a la de la regla de dependencia. Si una acción de dominio requiere disparar otro caso de uso de la capa de aplicación, será como reacción a un evento.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excepciones:&lt;/strong&gt; clases que representan errores comunes que se producen en nuestra aplicación. “&lt;em&gt;Usuario no encontrado”, “Dinero insuficiente”, “El valor no puede ser negativo…”,&lt;/em&gt; etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contratos:&lt;/strong&gt; por contratos, claro está, nos referimos a interfaces como pueden ser &lt;em&gt;UserRepository, LogReporter, ExceptionTracker…&lt;/em&gt; etc. Es decir, contratos que se deberán de implementar en la capa de infraestructura. Por ejemplo: &lt;em&gt;UserRepositoryMySQL, SumoLogicLogReporter&lt;/em&gt; o &lt;em&gt;SentryExceptionTracker.&lt;/em&gt; Estos contratos son los que nos permitirán implementar &lt;a href="https://martinfowler.com/articles/dipInTheWild.html"&gt;inversión de dependencias&lt;/a&gt; y nos darán la capacidad de cambiar estas dependencias, facilitando por ejemplo la transición de MySQL a MongoDB, ya que la interfaz (contrato) será la misma (&lt;em&gt;UserRepository&lt;/em&gt;), pero la implementación no (&lt;em&gt;UserRepositoryMySQL&lt;/em&gt; → &lt;em&gt;UserRepositoryMongo&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Aplicación
&lt;/h4&gt;

&lt;p&gt;En esta capa residirán los casos de uso, es decir, los orquestadores que, haciendo uso de elementos de dominio como entidades, excepciones, servicios, &lt;em&gt;value objects&lt;/em&gt;… los combinan para obtener una respuesta.&lt;/p&gt;

&lt;p&gt;Aquí se pueden aplicar patrones como &lt;a href="https://martinfowler.com/bliki/CommandQuerySeparation.html"&gt;CQS&lt;/a&gt; y &lt;a href="https://martinfowler.com/bliki/CQRS.html"&gt;CQRS&lt;/a&gt; o simplemente casos de uso más simples.&lt;/p&gt;

&lt;h4&gt;
  
  
  Infraestructura
&lt;/h4&gt;

&lt;p&gt;Aquí tenemos implementaciones de los distintos contratos que ha definido dominio. Esta es la capa que más puede variar su código a la hora de portar nuestro proyecto de un framework a otro o al cambiar de provider de base de datos o al cambiar una librería &lt;em&gt;third party&lt;/em&gt; por otra.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo de un flujo de aplicación
&lt;/h3&gt;

&lt;p&gt;Veamos un ejemplo del flow de un &lt;em&gt;endpoint&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FIiRdMe1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AdKMQDdjj0GfC7Qj-vKXhrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FIiRdMe1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AdKMQDdjj0GfC7Qj-vKXhrw.png" alt="" width="800" height="311"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Flujo de aplicación con la correspondencia de cada capa&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;En esta imagen podemos apreciar algunos de los componentes que intervienen en la ejecución de un &lt;em&gt;endpoint&lt;/em&gt;, y he asociado cada color al de la capa que pertenece.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Controlador:&lt;/strong&gt; aquí puede haber discrepancias y, en muchos casos, hay quien considera los controladores como parte de la capa de aplicación. Teóricamente es correcto, pero en la práctica nos encontramos con muchos frameworks que impiden que el controlador sea un elemento desacoplado, ya que tiene que heredar de ciertas clases para poder funcionar correctamente, así que en este ejemplo el controlador formará parte de la capa de infraestructura y lo consideraremos parte del framework.
Su misión en este caso es simplemente extraer los datos de la &lt;em&gt;request&lt;/em&gt;, encapsular los datos en un DTO y pasárselo al caso de uso para que lo maneje. Una vez reciba la respuesta, se encargará de elegir la presentación adecuada y devolver la respuesta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caso de uso:&lt;/strong&gt; esta es la parte de nuestro código que coordina la ejecución de la lógica de negocio. Puede incluir validaciones de los datos de entrada y la coordinación de distintos servicios de dominio para obtener la respuesta deseada, así como lanzar excepciones si se produce un error (esperado o inesperado).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Servicio.&lt;/strong&gt; Aquí es donde vive la lógica de nuestra aplicación, donde se ejecutan las políticas que hemos definido y donde reside todo el conocimiento.
Como se puede apreciar, los servicios de dominio pueden requerir del uso de elementos de infraestructura, pero nunca de forma directa, ya que hacemos uso de la &lt;a href="https://martinfowler.com/articles/dipInTheWild.html"&gt;inversión de dependencias&lt;/a&gt; para lograrlo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementaciones conocidas de Clean Architecture
&lt;/h3&gt;

&lt;p&gt;Ahora que ya sabes un poco más sobre arquitecturas limpias puede que te pique la curiosidad y quieras implementarla en tus proyectos. ¿Por dónde deberías empezar?&lt;/p&gt;

&lt;p&gt;Antes de nada lo más recomendable es que conozcas y domines algunas de las implementaciones más conocidas, así puedes decantarte por cuál se ajusta más a tu estilo, a tu lenguaje o a tu forma de pensar. Algunas de las implementaciones más conocidas son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hexagonal Architecture.&lt;/strong&gt; De Alistair Cockburn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onion Architecture.&lt;/strong&gt; De Jeffrey Palermo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screaming Architecture.&lt;/strong&gt; De Bob Martin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DCI.&lt;/strong&gt; De James Coplien.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BCE.&lt;/strong&gt; De Ivar Jacobson.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Puedes buscar más información sobre todas estas arquitecturas y aprender un poco más sobres sus principios y sus casos de uso, y no olvides estar atento a nuestro blog, porque trataremos muchas de ellas en próximos posts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bibliografia
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3NkW6in"&gt;&lt;strong&gt;Arquitectura Limpia.&lt;/strong&gt; Bob Martin (2018)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>cleancode</category>
      <category>architecture</category>
    </item>
    <item>
      <title>JSON Web Tokens</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Mon, 11 Sep 2023 07:52:42 +0000</pubDate>
      <link>https://dev.to/mangelsnc/json-web-tokens-2mnp</link>
      <guid>https://dev.to/mangelsnc/json-web-tokens-2mnp</guid>
      <description>&lt;h4&gt;
  
  
  API’s HTTP
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Autenticación stateless basada en tokens
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sWoVbFQt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AY4-jq2xzr5oO1xTA" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sWoVbFQt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AY4-jq2xzr5oO1xTA" alt="" width="800" height="535"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Jaye Haych on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/json-web-tokens-jwt/"&gt;&lt;strong&gt;Artículo escrito originalmente para Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Autenticación y gestión de la sesión en APIs
&lt;/h3&gt;

&lt;p&gt;Una de las principales características de las APIs es su condición de no tener estado, o por su término en inglés: de ser &lt;em&gt;stateless.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;¿Qué implica esto? Pues que cada vez que se recibe una petición hay que volver a recrear el estado, incluida la sesión del usuario y su autenticación.&lt;/p&gt;

&lt;p&gt;Puede parecer engorroso e innecesario, pero el hecho de ser &lt;em&gt;stateless&lt;/em&gt; es la característica principal que nos permite distribuir nuestra API en numerosos servidores sin necesidad de tener las sesiones persistidas de forma distribuida, lo cual &lt;strong&gt;sí es un engorro innecesario.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Obviamente, lo que no podemos hacer es solicitar al usuario que se autentique con cada petición que tenga que hacer al API, ya que esto sería una experiencia de uso nefasta. Para ello la solución más común es utilizar un sistema de autenticación basado en &lt;em&gt;tokens&lt;/em&gt;. Veamos un par de ejemplos:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Tokens JWT&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Las siglas JWT provienen de &lt;em&gt;JSON Web Tokens&lt;/em&gt;, y tal y como indica su nombre son unos &lt;em&gt;tokens&lt;/em&gt; basados en JSON. En realidad se trata de un estándar abierto que define una forma compacta y autocontenida para transmitir de forma segura información entre &lt;em&gt;backend&lt;/em&gt; y &lt;em&gt;frontend&lt;/em&gt; en forma de objeto JSON. Es segura porque esta información puede ser verificada y confiada ya que viene firmada digitalmente. Los &lt;em&gt;tokens&lt;/em&gt; JWT puede firmarse mediante el algoritmo &lt;strong&gt;HMAC&lt;/strong&gt; o mediante un sistema &lt;strong&gt;PKI&lt;/strong&gt; de claves públicas y privadas basadas en &lt;strong&gt;RSA&lt;/strong&gt; o  &lt;strong&gt;ECDSA.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Opcionalmente estos &lt;em&gt;tokens&lt;/em&gt; pueden ser encriptados para ocultar la información durante la transmisión entre ambas partes. La firma del token permite verificar la integridad de la información contenida en él, y al realizarse mediante claves públicas y privadas, garantiza que solo el &lt;em&gt;holder&lt;/em&gt; de la clave privada ha podido emitir esa información.&lt;/p&gt;

&lt;p&gt;Veamos un ejemplo de un _token _JWT:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eRVeQIUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AL_fKVCxtqnJVljFjMwme0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eRVeQIUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AL_fKVCxtqnJVljFjMwme0g.png" alt="" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como se puede observar hay una estructura de tres elementos separados por puntos, tal que así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xxxxxxxxxx.yyyyyyyyyy.zzzzzzzzzz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada una de estas secciones, codificadas en base64, son respectivamente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Header (Cabecera)&lt;/li&gt;
&lt;li&gt;Payload (Cuerpo)&lt;/li&gt;
&lt;li&gt;Signature (Firma)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Al realizar la decodificación de cada uno de estos elementos podemos ver el contenido de la cabecera y el cuerpo (la firma no va codificada):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sDXlWvqo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A4VBKHK0QL06M8D6Zjarqdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sDXlWvqo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A4VBKHK0QL06M8D6Zjarqdg.png" alt="" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Header
&lt;/h4&gt;

&lt;p&gt;Habitualmente la cabecera se compone de dos elementos: el tipo (&lt;em&gt;typ)&lt;/em&gt; que siempre en este caso es JWT, y el algoritmo que se usa para verificar la firma.&lt;/p&gt;

&lt;h4&gt;
  
  
  Payload
&lt;/h4&gt;

&lt;p&gt;El cuerpo por su parte se compone de una serie de atributos (o &lt;em&gt;claims&lt;/em&gt;) registrados (&lt;em&gt;sub, iss, exp, iat…)&lt;/em&gt; privados (&lt;em&gt;admin…)&lt;/em&gt; y públicos (&lt;em&gt;name).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;La lista de &lt;em&gt;claims&lt;/em&gt; registrados puede consultarse en la &lt;a href="https://www.rfc-editor.org/rfc/rfc7519#section-4.1"&gt;especificación oficial&lt;/a&gt;. Usualmente se componen solo de tres letras, ya que se supone que el &lt;em&gt;token&lt;/em&gt; debe de ser compacto. Veamos algunos de ellos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;iss:&lt;/strong&gt; &lt;em&gt;issuer&lt;/em&gt; o quién ha emitido el &lt;em&gt;token.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sub:&lt;/strong&gt; &lt;em&gt;subject&lt;/em&gt; o el motivo por el que se ha emitido el &lt;em&gt;token.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;exp:&lt;/strong&gt; &lt;em&gt;expiration,&lt;/em&gt; la fecha en que expirará el &lt;em&gt;token&lt;/em&gt;. Habitualmente en forma de &lt;em&gt;timestamp&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iat:&lt;/strong&gt; &lt;em&gt;issued at,&lt;/em&gt; la fecha en que se emitió el &lt;em&gt;token&lt;/em&gt;. Habitualmente en forma de &lt;em&gt;timestamp&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aud:&lt;/strong&gt; &lt;em&gt;audience,&lt;/em&gt; el público a quien va dirigido el &lt;em&gt;token&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usualmente el &lt;em&gt;claim&lt;/em&gt; más usado es el de &lt;em&gt;exp&lt;/em&gt;, ya que en muchos casos el resto son irrelevantes, pero la fecha de caducidad siempre es importante.&lt;/p&gt;

&lt;p&gt;Los &lt;em&gt;claims&lt;/em&gt; privados son todos aquellos que nosotros queramos incluir: nombre, email, id… todo cuanto necesitemos.&lt;/p&gt;

&lt;p&gt;Los &lt;em&gt;claims&lt;/em&gt; públicos pueden ser definidos por los usuarios de JWT, pero para evitar colisiones estos deben de estar registrados en el &lt;a href="https://www.iana.org/assignments/jwt/jwt.xhtml"&gt;&lt;em&gt;Registro IANA de JSON Web Tokens&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Signature
&lt;/h4&gt;

&lt;p&gt;Realizar la verificación de la firma es tan sencillo como utilizar la clave privada para firmar ese par de cabecera/cuerpo, y comprobar que coincide con la que nos envían para garantizar que el firmante está en posesión de la clave privada para realizar la firma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uso del token
&lt;/h3&gt;

&lt;p&gt;Tras realizar login con el API, esta nos devuelve un &lt;em&gt;token&lt;/em&gt; similar al que hemos visto antes, la forma de utilizar estos &lt;em&gt;tokens&lt;/em&gt; es incluirlos con la cabecera &lt;em&gt;Authorization&lt;/em&gt; de este modo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Authorization:** Bearer eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.jYW04zLDHfR1v7xdrW3lCGZrMIsVe0vWCfVkN2DRns2c3MN-mcp_-RE6TN9umSBYoNV-mnb31wFf8iun3fB6aDS6m_OXAiURVEKrPFNGlR38JSHUtsFzqTOj-wFrJZN4RwvZnNGSMvK3wzzUriZqmiNLsG8lktlEn6KA4kYVaM61_NpmPHWAjGExWv7cjHYupcjMSmR8uMTwN5UuAwgW6FRstCJEfoxwb0WKiyoaSlDuIiHZJ0cyGhhEmmAPiCwtPAwGeaL1yZMcp0p82cpTQ5Qb-7CtRov3N4DcOHgWYk6LomPR5j5cCkePAz87duqyzSMpCB0mCOuE3CU2VMtGeQ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La palabra clave &lt;em&gt;Bearer&lt;/em&gt; indica que es un token autocontenido. Mientras el token sea válido (el atributo &lt;em&gt;exp&lt;/em&gt; contiene la fecha de caducidad) el API nos dará acceso a la sesión del usuario logueado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refresh Tokens
&lt;/h3&gt;

&lt;p&gt;Habitualmente el TTL &lt;em&gt;(time to live)&lt;/em&gt; o duración del &lt;em&gt;token&lt;/em&gt;, es relativamente corto, ya que cualquiera que tenga el token podría impersonar la sesión. El problema es que no podemos estar pidiéndole cada dos por tres al usuario que se autentique, por lo que tenemos que ser creativos y buscar una alternativa.&lt;/p&gt;

&lt;p&gt;La alternativa preferida es el uso del &lt;em&gt;refresh token&lt;/em&gt;. El &lt;em&gt;refresh&lt;/em&gt; &lt;em&gt;token&lt;/em&gt; es un &lt;em&gt;token&lt;/em&gt; que nos permite obtener un nuevo &lt;em&gt;token&lt;/em&gt; de sesión sin necesidad de volver a introducir los credenciales del usuario. Por normal general el &lt;em&gt;refresh token&lt;/em&gt; tiene una duración muy superior a la del &lt;em&gt;token&lt;/em&gt; de sesión, y es responsabilidad del &lt;em&gt;frontend&lt;/em&gt; almacenarlo de la manera más segura posible.&lt;/p&gt;

&lt;p&gt;Al contrario que los &lt;em&gt;tokens&lt;/em&gt; de sesión, estos se guardan en base de datos y pueden invalidarse manualmente, por lo que si somos conscientes o sospechamos que hubo un robo del &lt;em&gt;token,&lt;/em&gt; podemos invalidarlos y dejar al atacante sin posibilidad de seguir utilizándolo.&lt;/p&gt;

&lt;p&gt;Además de esto, podemos tomar precauciones extra, como asociarlo a una IP en concreto o cualquier otra medida que nos parezca apropiada.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Basic Auth&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Esta es una forma de autenticación totalmente desaconsejada, ya que implica almacenar temporalmente la contraseña del usuario para realizar la autenticación.&lt;/p&gt;

&lt;p&gt;Básicamente consiste en realizar una codificación en &lt;em&gt;base64&lt;/em&gt; del nombre del usuario junto con su contraseña, separados por el carácter de los dos puntos y enviarlo en la cabecera &lt;em&gt;Authorization.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Supongamos que el usuario es &lt;a href="mailto:admin@secture.com"&gt;admin@secture.com&lt;/a&gt; y la contraseña p4ssW0rD entonces la cadena a codificar sería:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;admin@secture.com:p4ssW0rD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Daría como resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YWRtaW5Ac2VjdHVyZS5jb206cDRzc1cwckQ=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y la usaríamos de esta manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Authorization:** Basic YWRtaW5Ac2VjdHVyZS5jb206cDRzc1cwckQ=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso la palabra clave &lt;em&gt;Basic&lt;/em&gt; indicaría el tipo de autenticación.&lt;/p&gt;

&lt;p&gt;Como se puede ver, es muy sencillo que un potencial atacante &lt;em&gt;esnife&lt;/em&gt; el tráfico y obtenga la contraseña de nuestro usuario con una simple decodificación del &lt;em&gt;token.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Al tratar con APIs sin estado necesitamos hacer uso de algún método para recrear la sesión del usuario. Actualmente existen varias alternativas. Aquí hemos visto dos, pero solo recomendamos el uso de JWT, ya que es un estándar abierto, enfocado en la seguridad y la integridad de los datos y ampliamente usado en producción.&lt;/p&gt;

&lt;p&gt;La autenticación básica es solo un remanente de épocas pasadas que está condenado a desaparecer, ya que es totalmente inseguro.&lt;/p&gt;

&lt;p&gt;¡Desde Secture te animamos a dejar comentarios explicando qué otros medios usas para controlar las sesiones de los usuarios de tu API!&lt;/p&gt;

&lt;h3&gt;
  
  
  Bibliografía:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jwt.io/introduction"&gt;JSON Web Tokens (JWT)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Basic_access_authentication"&gt;Basic Access Authorization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>apidevelopment</category>
      <category>api</category>
      <category>token</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Patrón Money</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Tue, 29 Aug 2023 09:24:19 +0000</pubDate>
      <link>https://dev.to/mangelsnc/patron-money-4ipl</link>
      <guid>https://dev.to/mangelsnc/patron-money-4ipl</guid>
      <description>&lt;h4&gt;
  
  
  Maneja correctamente el dinero en tu aplicación y prepárala para el escalado internacional
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--64siAc8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Al-_ExGUeD2vo8xko" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--64siAc8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Al-_ExGUeD2vo8xko" alt="" width="800" height="534"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Jason Leung on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://secture.com/blog/patron-money-maneja-correctamente-el-dinero/"&gt;&lt;strong&gt;Artículo publicado originalmente para Secture&amp;amp;Code&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trabajar con cantidades de dinero nunca ha sido un asunto sencillo: redondeos, cambios de divisa… una mala gestión puede derivar en perdidas para nuestra empresa o en cobrar de más a nuestros clientes, con el consiguiente perjuicio reputacional.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;El patrón &lt;em&gt;Money&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Martin Fowler publicó en 2002 su famoso libro &lt;a href="https://amzn.to/3GhMvHD"&gt;&lt;em&gt;Patterns of Enterprise Application Architecture&lt;/em&gt;&lt;/a&gt;, donde uno de los patrones incluidos era el llamado patron &lt;em&gt;Money.&lt;/em&gt; Con este patrón, Fowler pretende simplificar la gestión de cantidades monetarias y reducir los posibles riesgos que antes comentábamos.&lt;/p&gt;

&lt;p&gt;El patrón &lt;em&gt;Money&lt;/em&gt; se basa en otro patrón conocido como &lt;a href="https://dev.to/mangelsnc/value-objects-1gd9"&gt;&lt;em&gt;Value Object&lt;/em&gt;&lt;/a&gt;, y consiste en modelar un pequeño objeto que represente una cantidad monetaria. Para ello se usan dos atributos: la cantidad (&lt;em&gt;amount&lt;/em&gt;), y la moneda (&lt;em&gt;currency&lt;/em&gt;), y una serie de operaciones lógicas y matemáticas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BEkuj0cw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/265/1%2A96rpkVsTvNI0Xy7iJDN8OA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BEkuj0cw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/265/1%2A96rpkVsTvNI0Xy7iJDN8OA.png" alt="" width="265" height="336"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Diagrama UML del Patrón Money&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Atributos
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;amount:&lt;/strong&gt; es el importe, representado siempre en la unidad mínima de la moneda asociada. Esta representación es perfecta para realizar comparaciones entre cantidades de una misma moneda, ya que las comparaciones entre números en coma flotante siguen siendo un asunto sin resolver en cualquier lenguaje.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Es importante saber que no todas las monedas son como el dólar o el euro, ya que no en todas la unidad mínima es el céntimo. Existen monedas donde la propia moneda es la unidad mínima, y otras donde no sólo tienen céntimos, sino que tienen unidades &lt;strong&gt;más pequeñas que el céntimo.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ejemplos de estos casos son el dinar de Bahrain, con milésimas partes del dinar, o el peso de Chile, donde no hay unidades inferiores al peso.&lt;/p&gt;

&lt;p&gt;Podemos consultar una lista con todas las monedas &lt;a href="https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=maintenance-agency"&gt;este enlace&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;currency:&lt;/strong&gt; es el código &lt;a href="https://en.wikipedia.org/wiki/ISO_4217"&gt;ISO-4217&lt;/a&gt; de la moneda con la que estamos trabajando. Es un código de 3 letras que representa la moneda de forma internacional, por ejemplo EUR para Euros.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Métodos / Operaciones
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;+, -, *, / :&lt;/strong&gt; operaciones matemáticas básicas, como la suma, resta, multiplicación, división…&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;allocate:&lt;/strong&gt; una operación especial destinada a dividir una cantidad de dinero entre dos o más receptores. Luego entraremos más en detalle.&lt;/li&gt;
&lt;li&gt;*&lt;em&gt;&amp;lt;, &amp;gt;, ≤, ≥, = *&lt;/em&gt; : operaciones lógicas básicas, como &lt;em&gt;menor que&lt;/em&gt;, &lt;em&gt;mayor que&lt;/em&gt;, &lt;em&gt;menor igual que&lt;/em&gt;, &lt;em&gt;mayor igual que&lt;/em&gt;, &lt;em&gt;igual&lt;/em&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ejemplos&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Queremos representar la cantidad 528.75€, cuya unidad mínima es el céntimo de euro:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;amount:&lt;/strong&gt; 52875&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;currency:&lt;/strong&gt; EUR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queremos representar la cantidad 528.75.د (dinares de Bahrain), cuya unidad mínima es la milésima parte de un dinar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;amount:&lt;/strong&gt; 528750&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;currency:&lt;/strong&gt; BHD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para representar visualmente la cantidad, solo necesitamos aplicar la sencilla fórmula: &lt;em&gt;amount / (10 x unidad mínima).&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementación
&lt;/h3&gt;

&lt;p&gt;Es sencillo realizar una implementación básica de este patrón, lo realmente tedioso es tener actualizada siempre la lista de monedas, con sus unidades mínimas o sus ratios de conversión.&lt;/p&gt;

&lt;p&gt;Veamos una implementación sencilla en PHP:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i6sJ3MQW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AaMNb1aPtzhqadVsNCi88Sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i6sJ3MQW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AaMNb1aPtzhqadVsNCi88Sg.png" alt="" width="800" height="1792"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Patrón Money básico en PHP&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A esta implementación básica le faltarían todos los métodos de las operaciones lógicas y matemáticas. He querido dejar de lado esta implementación para poder comentar que podemos hacerlo en dos versiones distintas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Orientado a objetos:&lt;/strong&gt; añadiendo los métodos add, substract, multiply, divide… Este sería el estilo orientado a objetos clásico. Nos permitiría tomar dos enfoques: mutable (modifica la instancia actual) o inmutable (no modifica la instancia, devuelve una nueva). De esta manera podremos ejecutar cosas como:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GUjvUhai--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANU-_VV6XKqq51D5FxmOMJA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GUjvUhai--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANU-_VV6XKqq51D5FxmOMJA.png" alt="" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sobrecarga de operadores:&lt;/strong&gt; muchos lenguajes orientados a objetos, como Java, PHP, Python o Ruby permiten lo que llamamos &lt;em&gt;sobrecarga de operadores&lt;/em&gt;, que no es más que permitir cambiar el comportamiento de los operadores aritméticos y lógicos cuando estos son aplicados a objetos de cierta clase, y no a tipos primitivos como se hace habitualmente.
Esto nos permitiría sobrecargar los operadores de tal manera que podríamos ejecutar algo así como:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3AAiVWqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AgeKh2oLrLUhKZTqY3Y87Eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3AAiVWqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AgeKh2oLrLUhKZTqY3Y87Eg.png" alt="" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La implementación básica de este patrón es realmente muy sencilla, pero si queremos sacarle el máximo provecho tenemos implementaciones en casi todos los lenguajes, que además cubren otros aspectos como la representación visual de la cantidad (situar el símbolo monetario a la derecha o a la izquierda), o la conversión entre divisas.&lt;/p&gt;

&lt;p&gt;Algunas implementaciones conocidas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PHP:&lt;/strong&gt; &lt;a href="https://github.com/moneyphp/money"&gt;https://github.com/moneyphp/money&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby:&lt;/strong&gt; &lt;a href="https://github.com/RubyMoney/money"&gt;https://github.com/RubyMoney/money&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; &lt;a href="https://github.com/poswald/python-money"&gt;https://github.com/poswald/python-money&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Método allocate
&lt;/h4&gt;

&lt;p&gt;Este método, como ya comentamos antes, es un método especial usado para distribuir adecuadamente una cantidad entre dos o mas receptores cuando no puede hacerse de forma exacta (sin sobras). Por ejemplo cuando lo hacemos basándonos en porcentajes o ratios.&lt;/p&gt;

&lt;p&gt;Veamos un caso específico:&lt;/p&gt;

&lt;p&gt;Queremos repartir 5cts de euro entre dos cuentas al 30%-70%. Esto implica un reparto de 1,5cts y 3,5cts. El problema es que el céntimo es la unidad mínima de la divisa euro, y no podemos partir un céntimo en dos, por lo tanto el reparto exacto no puede hacerse.&lt;/p&gt;

&lt;p&gt;La solución más habitual es repartir 1 céntimo a cada recipiente mientras no hayan llegado a la cantidad justa. Una vez haya sobrepasado esa cantidad, deja de recibir dinero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recipiente A: 1.5cts&lt;br&gt;&lt;br&gt;
Recipiente B: 2.5cts&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recipiente A:&lt;/strong&gt; 1cts (1 &amp;lt; 1.5 ✅). &lt;strong&gt;Recipiente B:&lt;/strong&gt; 1cts (1 &amp;lt; 2.5 ✅)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recipiente A:&lt;/strong&gt; 2cts (2 &amp;lt; 1.5 ❌). &lt;strong&gt;Recipiente B:&lt;/strong&gt; 2cts (2 &amp;lt; 2.5 ✅)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recipiente B:&lt;/strong&gt; 3cts (3 &amp;lt; 2.5 ❌)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Recipiente A:&lt;/strong&gt; 2cts&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Recipiente B:&lt;/strong&gt;  3cts&lt;/p&gt;

&lt;h3&gt;
  
  
  Bibliografia
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/eaaCatalog/money.html"&gt;&lt;em&gt;Money Pattern.&lt;/em&gt; &lt;strong&gt;Martin Fowler&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3GhMvHD"&gt;&lt;em&gt;Patterns of Enterprise Application Architecture.&lt;/em&gt; &lt;strong&gt;Martin Fowler (2002)&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=maintenance-agency"&gt;&lt;strong&gt;Lista de unidades mínimas de cada moneda&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/ISO_4217"&gt;&lt;strong&gt;Lista de códigos ISO-4217&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.tutsplus.com/tutorials/money-pattern-the-right-way-to-represent-value-unit-pairs--net-35509"&gt;&lt;em&gt;Money Pattern: The right way&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>softwarepatterns</category>
      <category>softwaredesignpatter</category>
      <category>cleancode</category>
      <category>moneypattern</category>
    </item>
    <item>
      <title>Command Query Responsibility Segregation | CQRS</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Fri, 04 Aug 2023 14:11:41 +0000</pubDate>
      <link>https://dev.to/mangelsnc/command-query-responsibility-segregation-cqrs-258l</link>
      <guid>https://dev.to/mangelsnc/command-query-responsibility-segregation-cqrs-258l</guid>
      <description>&lt;h4&gt;
  
  
  Prepara tu código para escalar hasta el infinito
&lt;/h4&gt;

&lt;p&gt;El patrón CQRS fue descrito por Greg Young en 2010 como una forma de separar los modelos de escritura (&lt;em&gt;commands)&lt;/em&gt; y de lectura (&lt;em&gt;queries&lt;/em&gt;) de nuestras aplicaciones, permitiendo de este modo un escalado asimétrico entre los mecanismos de lectura y escritura de nuestra aplicación.&lt;/p&gt;

&lt;p&gt;La idea básica es que podemos utilizar un modelo para escribir, distinto al modelo que usamos para ejecutar lecturas, como contrapunto al habitual &lt;em&gt;CRUD (&lt;/em&gt; &lt;strong&gt;&lt;em&gt;C&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;reate,&lt;/em&gt; &lt;strong&gt;&lt;em&gt;R&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;ead,&lt;/em&gt; &lt;strong&gt;&lt;em&gt;U&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;pdate,&lt;/em&gt; &lt;strong&gt;&lt;em&gt;D&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;elete).&lt;/em&gt; Cabe decir que esta aproximación, la de CQRS, puede añadir una mayor complejidad que un sistema sencillo basado en &lt;em&gt;CRUD.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Implementación de CQRS&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Separación de los modelos
&lt;/h4&gt;

&lt;p&gt;Podemos implementar CQRS de distintas maneras en función de nuestras necesidades.&lt;/p&gt;

&lt;p&gt;Por ejemplo, podemos optar por mantener una única base de datos y realizar solo una separación a nivel de conexión, es decir, usaremos una conexión diferente para las operaciones de lectura &lt;em&gt;(queries)&lt;/em&gt; y las de escritura &lt;em&gt;(commands)&lt;/em&gt;. Esto nos permiten configurar distintos parámetros como &lt;em&gt;timeouts&lt;/em&gt;, tamaño de peticiones y otros parámetros más ajustados a la naturaleza de la operación.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---HCqKv38--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AqjvXpl9NV4x1nModu1ne8Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---HCqKv38--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AqjvXpl9NV4x1nModu1ne8Q.png" alt="" width="800" height="182"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;CQRS con base de datos unificada&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Esta aproximación tiene el inconveniente de que la separación solo existe a un nivel lógico, es decir, seguimos atacando la misma base de datos, por lo que sigue siendo el mismo sistema el que asume la carga de trabajo.&lt;/p&gt;

&lt;p&gt;Otra aproximación sería utilizar dos bases de datos separadas para escrituras y lecturas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KnPRYjfg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AOJAXpdregMKLoWqKTUlQrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KnPRYjfg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AOJAXpdregMKLoWqKTUlQrw.png" alt="" width="800" height="212"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;CQRS con bases de datos separadas&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;De este modo, la carga de las operaciones de lectura y escritura están más repartidas y no solo a un nivel lógico, sino que son dos sistemas diferentes los que manejan esta carga. El inconveniente de esta aproximación es que se genera una &lt;em&gt;consistencia eventual&lt;/em&gt;, es decir, los modelos de lectura y escritura no serán consistentes en todo momento, sino que eventualmente existirán diferencias entre ellos, lo cual puede generar un problema en función de la naturaleza de los datos.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementación de los modelos
&lt;/h4&gt;

&lt;p&gt;Al implementar las operaciones de lectura y escritura vamos a tener 3 nuevas parejas de actores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Query&lt;/em&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;em&gt;QueryHandler.&lt;/em&gt;&lt;/strong&gt;
Son, respectivamente, el modelo de lectura y su manejador. La &lt;em&gt;query&lt;/em&gt; no es más que un DTO con toda la información necesaria para realizar la lectura (parámetros, filtros, paginación…). Por su parte el &lt;em&gt;handler&lt;/em&gt; o manejador es el servicio encargado de obtener esa información y devolvérsela al controlador.
Por norma general, las operaciones de lectura son siempre síncronas.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;La correspondencia de queries y handlers es 1:1, es decir, cada query tiene solo un handler, no puede ser manejado por más de uno.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Command&lt;/em&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;em&gt;CommandHandler.&lt;/em&gt;&lt;/strong&gt;
Son respectivamente el modelo de escritura y su manejador. El &lt;em&gt;command&lt;/em&gt; no es más que un DTO con toda la información necesaria para realizar la escritura (identificador del registro(s) a editar, atributos a modificar…). Por su parte el &lt;em&gt;handler&lt;/em&gt; o manejador es el servicio encargado de persistir esa información.
Las operaciones de escritura pueden ser síncronas o asíncronas, lo cual representa una ventaja en términos de eficiencia, ya que podemos simplemente lanzar la acción de actualización sin esperar a que ésta acabe: el &lt;em&gt;frontend&lt;/em&gt; ya tiene los datos actualizados, ya que es él quien nos los ha mandado.
Debemos de tener, eso sí, mecanismos para reaccionar de cara a problemas de escritura de datos asíncronos (sistema de reintentos, notificaciones al frontend vía server &lt;em&gt;push&lt;/em&gt; o &lt;em&gt;sockets…&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;La correspondencia de&lt;/em&gt; commands &lt;em&gt;y&lt;/em&gt; handlers &lt;em&gt;es 1:1, es decir, cada&lt;/em&gt; command &lt;em&gt;tiene solo un&lt;/em&gt; handler_, no puede ser manejado por más de uno._&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Event&lt;/em&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;em&gt;EventHandler.&lt;/em&gt;&lt;/strong&gt;
En este caso son, respectivamente, el modelo de &lt;em&gt;algo que ha sucedido&lt;/em&gt; en nuestro sistema y su manejador. El &lt;em&gt;event&lt;/em&gt; no es más que un DTO con la información de lo que ha sucedido, normalmente se compone de una fecha o &lt;em&gt;timestamp&lt;/em&gt; de cuándo ha ocurrido, un nombre descriptivo, siempre en pasado, de lo sucedido (por ejemplo: &lt;em&gt;user_deleted)&lt;/em&gt; y un cuerpo o &lt;em&gt;payload&lt;/em&gt; con toda la información relevante para manejar el evento. Este &lt;em&gt;payload&lt;/em&gt; puede componerse de datos necesarios para identificar el registro afectado, los atributos que se han modificado… etc.
Al igual que los &lt;em&gt;commands&lt;/em&gt;, los eventos pueden manejarse de forma síncrona o asíncrona, asegurándonos de tomar las mismas precauciones para gestionar posibles errores.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Al contrario que en los casos anteriores, la correspondencia de &lt;em&gt;eventos&lt;/em&gt; y &lt;em&gt;handlers&lt;/em&gt; (o listeners) es 1:n, es decir, cada event tiene más de un handler o &lt;em&gt;listener&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Un caso de uso muy común de los eventos es eliminar la consistencia eventual producida en sistemas con bases de datos separadas: tras realizarse una actualización, eliminación o inserción de datos en la base de datos de escritura, un evento avisa de los cambios para que estos se repliquen en la base de datos de lectura.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R0klozlE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AppThCN7nsAHjmVMMLMJTGA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R0klozlE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AppThCN7nsAHjmVMMLMJTGA.png" alt="" width="800" height="190"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Actualización del modelo de lectura mediante eventos&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Manejo síncrono o asíncrono de los modelos
&lt;/h4&gt;

&lt;p&gt;Para permitir el manejo síncrono o asíncrono de los modelos solemos hacer un uso de un sistema intermedio que se encarga de emparejar los &lt;em&gt;commands&lt;/em&gt;, las &lt;em&gt;queries&lt;/em&gt; y los &lt;em&gt;events&lt;/em&gt; con sus respectivos &lt;em&gt;handlers.&lt;/em&gt; Este sistema intermedio es lo que llamamos un &lt;em&gt;bus.&lt;/em&gt; El bus es como una cola donde metemos los &lt;em&gt;commands, queries&lt;/em&gt; o &lt;em&gt;events&lt;/em&gt; y estos son ejecutados por sus &lt;em&gt;handlers&lt;/em&gt; asociados. Este &lt;em&gt;bus&lt;/em&gt; puede implementarse con sistemas como &lt;em&gt;Message Queues Systems (RabbitMQ)&lt;/em&gt; o sistemas como &lt;em&gt;Redis&lt;/em&gt; que permiten el encolado de tareas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Na187hiL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AlkeVORD99EJ7uf3QTAOfIA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Na187hiL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AlkeVORD99EJ7uf3QTAOfIA.png" alt="" width="800" height="420"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Flujo síncrono de un endpoint para obtener una entidad de base de datos&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;La ventaja del uso de buses en forma de colas de mensajes es que añadimos una capa de &lt;a href="https://es.wikipedia.org/wiki/Indirecci%C3%B3n"&gt;indirección&lt;/a&gt; entre la acción y la ejecución. Esto quiere decir que la tarea encolada puede ser consumida por nuestro propio sistema o por un sistema externo que se conecte al servicio de colas, permitiéndonos esto el tener sistemas externos encargados de manejar, por ejemplo, la consistencia eventual, o delegar tareas largas y pesadas a sistemas expertos en realizar estas mismas tareas, que puede que ni siquiera estén escritos en el mismo lenguaje que nuestro sistema principal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lyXCc5T9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjdgOP9xPifVMrlYZVH-1aA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lyXCc5T9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjdgOP9xPifVMrlYZVH-1aA.png" alt="" width="800" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Flujo asíncrono de un endpoint de actualización de un registro que incluye el disparo de un evento.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Veamos un ejemplo de como nuestro sistema podría manejar la consistencia eventual (sin el uso de agentes externos):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2nxKtEW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjrlVgqvE-VN250vxMHozzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2nxKtEW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjrlVgqvE-VN250vxMHozzg.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Manejo de la consistencia eventual con eventos en un sistema de buses.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;En el ejemplo de arriba vemos como el &lt;em&gt;command handler&lt;/em&gt; dispara un evento al bus de eventos. Este evento puede ser la notificación de que se ha escrito un nuevo registro, o que se ha editado o eliminado uno que ya existía previamente. Puede representar más cosas, como que se ha suscrito a un servicio, que ha hecho &lt;em&gt;like&lt;/em&gt; a una foto… lo que sea. El tema es que este evento es capturado por el handler asociado y actúa en consonancia actualizando la base de datos de lectura, tratando de reducir al máximo el tiempo de consistencia eventual.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ventajas de CQRS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Escalado asimétrico.&lt;/strong&gt;
En entornos de alta disponibilidad, donde se producen miles de interacciones por segundo y hay flujos con más tráfico que otros, el escalado asimétrico de nuestra plataforma es algo realmente deseable, ya que podemos centrar el esfuerzo económico en esa parte únicamente. En el caso de CQRS, el tener separados los dominios de escritura y los de lectura nos permite centrar nuestros esfuerzos económicos en el que requiera mayor inversión.
¿Tenemos un proyecto tipo red social donde la gente se pasa más tiempo leyendo contenido que produciéndolo? Incrementamos las instancias de lectura, escalamos las instancias… lo que sea necesario, pero sólo centrado en las de lectura.
¿Nuestro proyecto es como un API en la que sensores a lo largo de cientos de instalaciones escriben registros cada segundo o minuto? Nos centramos en escalar la escritura, ya que, seguramente, haya poca gente consultando el panel de lecturas si lo comparamos con el número de escrituras.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separación de dominios más semántica.&lt;/strong&gt;
Esta ventaja es más a nivel organizativo, pero el hecho de tener separados nuestros casos de uso entre lecturas y escrituras simplifica mucho el entendimiento del mismo. Por ejemplo, sabemos seguro que una lectura no va a tener &lt;em&gt;side effects&lt;/em&gt; o que podemos ejecutarla tantas veces como queramos sin repercusiones. Luego, la separación de los &lt;em&gt;side effects&lt;/em&gt; que puedan producir las escrituras, al manejarse con eventos nos permite centrar el caso de uso en su propósito único, y delegar estos &lt;em&gt;side effects&lt;/em&gt; a otras porciones de código, quedando todo mucho más limpio y organizado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvenientes de CQRS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complejidad.&lt;/strong&gt;
El hecho de tener que implementar CQRS incrementa notablemente la complejidad de nuestro sistema, tanto por tener el doble de configuraciones o instancias de base de datos, como por la necesidad del uso de &lt;em&gt;buses&lt;/em&gt; (aunque esto es realmente opcional). Si no estamos acostumbrados a trabajar por capas puede ser un cambio realmente brusco, aunque a medio/largo plazo la situación mejora ostensiblemente.
Un problema derivado de la complejidad es que necesitamos un equipo senior formado para diseñar nuestra estrategia y montar un flow de trabajo que luego puedan seguir nuestros compañeros más juniors, pero un buen diseño puede derivar en un proceso casi mecánico para implantar nuevos casos de uso basados en &lt;em&gt;commands&lt;/em&gt; y &lt;em&gt;queries.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistencia eventual.&lt;/strong&gt;
Éste es el verdadero gran inconveniente de CQRS, ya que, dependiendo de lo urgente que sea tener nuestros datos actualizados, puede ser una buena opción o no, debido a que tendremos que garantizar un tiempo mínimo para que sean consistentes ambas bases de datos. Luego derivado de esto pueden darse problemas con la entrega de datos de los &lt;em&gt;buses&lt;/em&gt;, que pueden llegar repetidos o desordenados, y es algo que también tenemos que controlar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A continuación veremos una técnica para facilitar la gestión de la consistencia eventual llamada &lt;em&gt;Event Sourcing.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistencia eventual y Event Sourcing
&lt;/h3&gt;

&lt;p&gt;Event Sourcing es un patrón o técnica que podemos utilizar para tratar de simplificar los problemas de consistencia eventual, así como añadir una serie de beneficios a nuestro sistema, tales como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidad.&lt;/strong&gt; Sabemos por qué un registro está en el estado que está.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tolerancia a fallos.&lt;/strong&gt; Podemos reconstruir los registros a partir de los eventos guardados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditoria.&lt;/strong&gt; Estrechamente relacionado con la observabilidad, nos permite auditar las acciones que tienen lugar en nuestro sistema y podemos determinar flujos de datos erróneos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ¿En qué consiste el &lt;em&gt;Event Sourcing&lt;/em&gt;?
&lt;/h4&gt;

&lt;p&gt;Es un patrón mediante el cual registramos en una base de datos separada o &lt;em&gt;event store&lt;/em&gt; todos los eventos que se producen en nuestro sistema, de modo que formen un histórico de cambios asociado a un registro de nuestra base de datos. Esto nos permite reconstruir un registro a cualquier momento del flujo de vida de nuestro sistema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x4uRtMQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AQuPUKisuzG55wL1DPJbCIg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4uRtMQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AQuPUKisuzG55wL1DPJbCIg.png" alt="" width="800" height="452"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Cadena de eventos producida por command handlers y consumidos por la base de datos de lectura para recrear el estado de un registro.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Los eventos, por supuesto, deben de guardar la fecha en la que fueron lanzados, ya que esta es la que determinara su orden en la cadena. También es importante que guarden el identificador del registro de base de datos al que pertenecen, de modo que cuando queramos recrear un registro o desplazarnos hasta un momento en el tiempo, es necesario poder identificar el registro en cuestión.&lt;/p&gt;

&lt;p&gt;El &lt;em&gt;event sourcing&lt;/em&gt; solo se aplica en los modelos de escritura, ya que las lecturas no afectan al estado de los registros.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué nos aporta CQRS a nosotros?
&lt;/h3&gt;

&lt;p&gt;Para nosotros CQRS ha sido todo un cambio para mejor, ya que nos ha permitido fijar un modo de trabajo común que simplifica mucho el entendimiento de los proyectos, y esto incluye cuando nos movemos entre proyectos en los que no hemos participado nunca.&lt;/p&gt;

&lt;p&gt;Aunque de entrada se percibe como un sistema complejo (y lo es), las ventajas que nos aporta a nivel testabilidad, mantenibilidad y escalabilidad de nuestro código (así como la ya mencionada facilidad de rotación entre proyectos), compensan con creces los inconvenientes.&lt;/p&gt;

&lt;p&gt;Cabe decir que en proyectos menores hemos tomado decisiones que simplifican todo o que anulan parte de los inconvenientes, como por ejemplo usar comandos síncronos o directamente eliminar los &lt;em&gt;buses&lt;/em&gt; de &lt;em&gt;queries&lt;/em&gt; y de &lt;em&gt;commands&lt;/em&gt;, que borran de un plumazo gran parte de los problemas.&lt;/p&gt;

&lt;p&gt;Adaptar los patrones a la necesidad de cada proyecto también es una decisión estratégica que hay que tomar, ya que debemos de estar seguros de sus implicaciones y su facilidad de revertir esas adaptaciones, ya que si un proyecto crece, puede que necesitemos esos extras que nos aporta el patrón original.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bibliografía
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf"&gt;&lt;strong&gt;CQRS Documents.&lt;/strong&gt; Greg Young (2010)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/bliki/CQRS.html"&gt;&lt;strong&gt;CQRS.&lt;/strong&gt; Martin Fowler (2011)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leanpub.com/cqrs-by-example"&gt;&lt;strong&gt;CQRS By Example.&lt;/strong&gt; Carlos Buenosvinos y Christian Soronellas (2022)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3t0NKmJ"&gt;&lt;strong&gt;Domain-Driven Design in PHP.&lt;/strong&gt; Carlos Buenosvinos y Christian Soronellas (2016)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.netmentor.es/entrada/event-sourcing-explicado-facil"&gt;&lt;strong&gt;Event Sourcing explicado fácil.&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>eventualconsistency</category>
      <category>cleanarchitecture</category>
      <category>cleancode</category>
      <category>eventsourcing</category>
    </item>
    <item>
      <title>Arquitectura Hexagonal 101</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Thu, 20 Jul 2023 11:04:14 +0000</pubDate>
      <link>https://dev.to/mangelsnc/arquitectura-hexagonal-101-b6e</link>
      <guid>https://dev.to/mangelsnc/arquitectura-hexagonal-101-b6e</guid>
      <description>&lt;h4&gt;
  
  
  Arquitecturas Limpias
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Todo lo que necesitas saber sobre Arquitectura Hexagonal
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hKqxV6zE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/859/1%2A1nYwAqW8WRCDqY-PJdyskA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hKqxV6zE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/859/1%2A1nYwAqW8WRCDqY-PJdyskA.png" alt="" width="800" height="594"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Esquema de arquitectura hexagonal.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Artículo escrito originalmente para el blog &lt;a href="https://secture.com/blog/arquitectura-hexagonal-101/"&gt;&lt;strong&gt;Secture &amp;amp; Code&lt;/strong&gt;&lt;/a&gt; pulsa en el enlace para leerlo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La Arquitectura Hexagonal, definida por &lt;a href="https://alistair.cockburn.us/hexagonal-architecture/"&gt;Alistair Cockburn&lt;/a&gt;, es una implementación de lo que llamamos una &lt;em&gt;Clean Architecture.&lt;/em&gt; Tiene como principal motivación dividir nuestra aplicación en distintas capas con su propia responsabilidad. Esta separación por capas nos permite desacoplar nuestro código de las dependencias externas, como puede ser el framework o cualquier otra librería externa o &lt;em&gt;third party.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ports and adapters
&lt;/h3&gt;

&lt;p&gt;Esta arquitectura también es ampliamente conocida como arquitectura de puertos y adaptadores, o por su nombre en inglés &lt;em&gt;ports&amp;amp;adapters.&lt;/em&gt; Y es justo porque hace un uso intensivo del patrón “adaptador” (&lt;a href="https://refactoring.guru/design-patterns/adapter"&gt;&lt;em&gt;Adapter Pattern&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt; junto con el &lt;a href="https://martinfowler.com/articles/dipInTheWild.html"&gt;principio de inversión de dependencias&lt;/a&gt; para obtener ese desacoplamiento del que antes hablábamos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué hexagonal?
&lt;/h3&gt;

&lt;p&gt;En casi todos los textos o documentos que hablan de esta arquitectura, solemos verla representada con forma de hexágono. ¿Y por qué un hexágono y no un pentágono, o un triangulo o cualquier otro polígono? No hay una respuesta oficial al respecto, simplemente &lt;a href="https://www.youtube.com/watch?v=thOifuHs6eY"&gt;puede ser porque el hexágono es el polígono más versátil&lt;/a&gt;. Sea como sea, el número de lados no es relevante, es solo un arreglo meramente cosmético para diferenciarla del resto de arquitecturas limpias.&lt;/p&gt;

&lt;p&gt;El hecho es que cada lado representa un puerto de entrada/salida de la aplicación, y una forma poligonal expresa mejor que un círculo este principio.&lt;/p&gt;

&lt;p&gt;Estos puertos son el punto de entrada de cualquiera de los agentes externos o mecanismos que pueden interactuar con nuestra aplicación, bien sean estos clientes mobile o web a través del puerto para &lt;em&gt;REST API&lt;/em&gt;, navegadores web a través del puerto HTTP o un sistema de colas a través del puerto para &lt;em&gt;Message Brokers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cada uno de estos puertos tiene, a su vez, asignado uno o varios adaptadores, en función de la diversidad que queramos soportar. Por ejemplo, el puerto para &lt;em&gt;MessageBrokers&lt;/em&gt; podría perfectamente tener adaptadores para RabbitMQ, Redis, Beanstalk o AmazonSQS, si lo que queremos es dar soporte a toda esta variedad de &lt;em&gt;providers&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puntos en común con Clean Architecture
&lt;/h3&gt;

&lt;p&gt;Anteriormente ya hablamos de &lt;a href="https://medium.com/secture/clean-architectures-101-95a31b79ddb4"&gt;&lt;em&gt;Clean Architectures&lt;/em&gt;&lt;/a&gt; y sus características, por lo que sería recomendable echar un vistazo al post en el que hablamos de este tema, ya que la arquitectura hexagonal es una de las implementaciones más puras que podemos encontrar de &lt;em&gt;Clean Architecture.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tanto la distribución de las capas como su contenido o las reglas de dependencia son literalmente las mismas, pero igualmente vamos a ver sus características.&lt;/p&gt;

&lt;h3&gt;
  
  
  La regla de dependencia
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hKqxV6zE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/859/1%2A1nYwAqW8WRCDqY-PJdyskA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hKqxV6zE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/859/1%2A1nYwAqW8WRCDqY-PJdyskA.png" alt="" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cada uno de los hexágonos concéntricos representa una capa, y esta capa a su vez es una barrera que sólo puede ser atravesada por sus capas superiores. De este modo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infraestructura&lt;/strong&gt; puede acceder a &lt;strong&gt;Aplicación&lt;/strong&gt; y a  &lt;strong&gt;Dominio&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicación&lt;/strong&gt; puede acceder a  &lt;strong&gt;Dominio&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dominio&lt;/strong&gt; sólo puede acceder a  &lt;strong&gt;Dominio&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuanto más hacia dentro penetramos en las capas, más nos adentramos en la lógica de negocio, las reglas y las políticas. Cuanto más hacia fuera nos movemos, más cerca estamos de los agentes externos o mecanismos (clientes web o mobile, servicios externos o APIs, servicios de infraestructura como bases de datos, sistemas de colas, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Estructura de directorios y separación por capas
&lt;/h3&gt;

&lt;p&gt;Vamos a ver paso por paso la estructura de directorios y cómo se distribuye el código en las distintas capas. Empezaremos por un ejemplo básico que iremos iterando.&lt;/p&gt;

&lt;p&gt;En primer lugar, la raíz de nuestro proyecto podría ser esta:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C1akEN8_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/286/1%2AEdqbBQ1TULAKAndghQvLhg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C1akEN8_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/286/1%2AEdqbBQ1TULAKAndghQvLhg.png" alt="" width="286" height="370"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Raíz del proyecto&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;apps&lt;/strong&gt; contiene las aplicaciones, las instalaciones de los distintos frameworks que usemos. Aquí es donde vivirán nuestros controladores y nuestras rutas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;src&lt;/strong&gt; contendrá nuestro código, la lógica de negocio de nuestra aplicación.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vAik76aC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/724/1%2Ay2C5_r0wgsWtRq_yxWlpsQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vAik76aC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/724/1%2Ay2C5_r0wgsWtRq_yxWlpsQ.png" alt="" width="724" height="744"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Aplicación API&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Aquí podemos observar desplegado el contenido de una aplicación. Por razones de espacio hemos obviado toda carpeta no relevante, dejando a la vista solo el &lt;em&gt;entrypoint&lt;/em&gt; (index.php) y los controladores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--td6VolsD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/656/1%2AWonIdGlijk03B0WelOaCQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--td6VolsD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/656/1%2AWonIdGlijk03B0WelOaCQg.png" alt="" width="656" height="966"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Contexto y módulos de API&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hemos optado por una distribución en contextos (&lt;em&gt;API&lt;/em&gt; y &lt;em&gt;Shared&lt;/em&gt;). En este caso solo tenemos un contexto funcional &lt;em&gt;(API)&lt;/em&gt; y otro compartido &lt;em&gt;(Shared)&lt;/em&gt;, pero podríamos tener más como, por ejemplo, &lt;em&gt;backoffice,&lt;/em&gt; que podría contener todo el código para gestionar una aplicación de gestión de contenidos.&lt;/p&gt;

&lt;p&gt;Como se puede apreciar, cada módulo contiene su tripleta de carpetas, correspondiente cada una a una de las capas de la arquitectura.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1aAvEeIp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ArHF9TIklP-ViYU3UgV5pTA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1aAvEeIp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ArHF9TIklP-ViYU3UgV5pTA.png" alt="" width="800" height="1402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Módulo Users expandido&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Entrando más en detalle, podemos ver el contenido de cada una de las carpetas que conforman la arquitectura:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Application.&lt;/strong&gt; Casos de uso. En nuestro caso aplicamos CQRs, por lo que normalmente se componen de una &lt;em&gt;query&lt;/em&gt; (acción de lectura) o un &lt;em&gt;command&lt;/em&gt; (acción de escritura), un &lt;em&gt;handler&lt;/em&gt; o manejador y, opcionalmente, un servicio que ejecute la acción. En algunos casos este servicio puede ser compartido por otros casos de uso, como por ejemplo en el caso de &lt;em&gt;GetUser&lt;/em&gt;, por lo cual promocionamos el servicio de &lt;em&gt;application service&lt;/em&gt; a &lt;em&gt;domain service,&lt;/em&gt; situándolo en la carpeta &lt;em&gt;Domain&lt;/em&gt; y haciéndolo accesible al resto de casos de uso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain.&lt;/strong&gt; Aquí es donde alojamos los objetos de dominio, como la entidad &lt;em&gt;User&lt;/em&gt; que representa a un usuario, o los contratos de servicios que se implementarán en infraestructura, como &lt;em&gt;UserRepository.&lt;/em&gt; También consideramos objetos de dominio las excepciones, y algunos servicios compartidos como el anteriormente citado &lt;em&gt;GetUser.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure.&lt;/strong&gt; Por último tenemos las implementaciones de los contratos de dominio. En este caso solo tenemos una implementación del repositorio y sería para el motor de bases de datos &lt;em&gt;MySQL&lt;/em&gt;, pero perfectamente podríamos soportar más con solo implementar el contrato.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nEj_Q7dI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AehGYmBolCKq-2wGjKVTWOQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nEj_Q7dI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AehGYmBolCKq-2wGjKVTWOQ.png" alt="" width="800" height="1067"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Contexto compartido expandido&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Antes hablábamos de un &lt;em&gt;contexto compartido&lt;/em&gt;, y es aquí donde van la mayor parte de los contratos y de las implementaciones de elementos que se van a utilizar por toda la aplicación, como pueden ser por ejemplo un &lt;em&gt;EventDispatcher,&lt;/em&gt; o los buses de &lt;em&gt;commands&lt;/em&gt; y &lt;em&gt;queries&lt;/em&gt;. En este ejemplo, hemos implementado un bus con dos proveedores diferentes: &lt;em&gt;Symfony&lt;/em&gt; y &lt;em&gt;Tactician.&lt;/em&gt; Y, además, hemos realizado dos implementaciones diferentes para cada una: la versión síncrona y la asíncrona.&lt;/p&gt;

&lt;p&gt;Con esto pretendemos demostrar la versatilidad que nos ofrece esta arquitectura y la facilidad de cambio que nos aporta a nuestro código: podríamos cambiar la forma en que se manejan nuestros &lt;em&gt;commands&lt;/em&gt; y nuestras &lt;em&gt;queries&lt;/em&gt; con solo alterar unos parámetros de configuración del container de dependencias.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arquitectura hexagonal y DDD
&lt;/h3&gt;

&lt;p&gt;Habremos visto mil y una veces el termino de arquitectura hexagonal junto con el de &lt;a href="http://dddcommunity.org/learning-ddd/what_is_ddd/"&gt;DDD&lt;/a&gt;, y es que sin duda son un &lt;em&gt;killer combo&lt;/em&gt; muy socorrido.&lt;/p&gt;

&lt;p&gt;El DDD es una metodología de desarrollo que defiende el desacoplamiento por encima de todo, por lo que la Arquitectura Hexagonal encaja como un guante como núcleo central en su práctica.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bibliografia
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://alistair.cockburn.us/hexagonal-architecture/"&gt;&lt;strong&gt;Hexagonal Architecture.&lt;/strong&gt; Alistair Cockburn (2005)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.c2.com/?HexagonalArchitecture"&gt;&lt;strong&gt;Hexagonal Architecture Draft.&lt;/strong&gt; Alistair Cockburn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>hexagonalarchitectur</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>APIs HTTP</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Sun, 13 Nov 2022 11:40:47 +0000</pubDate>
      <link>https://dev.to/mangelsnc/apis-http-2a3i</link>
      <guid>https://dev.to/mangelsnc/apis-http-2a3i</guid>
      <description>&lt;h4&gt;
  
  
  Expón tus APIs al mundo entero
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mI7SuF0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AurmQ__lhdFhgzynmeEd5mA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mI7SuF0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AurmQ__lhdFhgzynmeEd5mA.jpeg" alt="" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si hay un concepto en el mundo del desarrollo que haya cobrado fuerza estos últimos años, sin duda es el término API.&lt;/p&gt;

&lt;p&gt;No hay proyecto que se precie que no tenga su API, pública o privada, o que haga uso de APIs de terceros para obtener información o integrar servicios de una forma mas o menos sencilla.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pero, ¿qué es una API?
&lt;/h3&gt;

&lt;p&gt;Las siglas API corresponden al término &lt;em&gt;Application Programming Interface,&lt;/em&gt; que podríamos traducir como &lt;em&gt;interfaz de programación de aplicaciones.&lt;/em&gt; Y es que un API no es más que un conjunto de funciones que nos ofrece un sistema, y que nosotros, combinándolas de forma adecuada, nos permite crear aplicaciones o nuevas funcionalidades.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tipos de APIs
&lt;/h4&gt;

&lt;p&gt;Pero una API no sólo puede tener la forma de un servicio HTTP, el concepto es mucho más amplio que eso. Por ejemplo, en el paradigma de la programación orientada a objetos (POO), el &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#method.summary"&gt;conjunto de métodos públicos de una clase&lt;/a&gt; se puede considerar su API.&lt;/p&gt;

&lt;p&gt;Cuando descargamos una biblioteca de terceros en nuestro proyecto, &lt;a href="https://axios-http.com/docs/api_intro"&gt;el conjunto de servicios y funciones que podemos usar&lt;/a&gt; es también el API de esta biblioteca.&lt;/p&gt;

&lt;p&gt;Si desarrollamos aplicaciones para Android, iOS, Linux, Windows, MacOS… estos sistemas ofrecen APIs que nos permiten interactuar con sistema para que podamos hacer cosas como abrir ventanas, capturar notificaciones del sistema, integrar nuestra app con el sistema para que tenga un aspecto nativo, incluir nuevas acciones en menús… etc.&lt;/p&gt;

&lt;p&gt;Y, por supuesto, &lt;a href="https://developer.marvel.com/docs"&gt;el conjunto de endpoints que nos permite interactuar con un servicio HTTP&lt;/a&gt;, es también un API. En este caso un API HTTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  APIs HTTP
&lt;/h3&gt;

&lt;p&gt;El concepto de API es el mismo, pero en este caso las funcionalidades en lugar de estar en una biblioteca que hemos importado o ser parte de un sistema para el que queremos desarrollar, están en un servidor externo que nos ofrece estas funcionalidades y la forma de comunicarnos con el servidor es a través del protocolo HTTP.&lt;/p&gt;

&lt;p&gt;Dada esta característica, es muy importante conocer cómo funciona el protocolo HTTP, ya que entender los pormenores de HTTP nos va a permitir comprender el funcionamiento de la API.&lt;/p&gt;

&lt;p&gt;Vamos a dar un repaso rápido a los conceptos más importantes del protocolo HTTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protocolo HTTP
&lt;/h3&gt;

&lt;p&gt;El protocolo HTTP es un protocolo de comunicación de red. Está basado en peticiones y respuestas (requests y responses) que deben de seguir un formato en concreto. Es un protocolo &lt;strong&gt;no orientado a conexión&lt;/strong&gt; , es decir, tras obtener la respuesta a una petición, la conexión se cierra en lugar de mantenerse a la espera de recibir más peticiones. Dicho de otro modo: no mantiene el estado.&lt;/p&gt;

&lt;p&gt;Es un protocolo multimedia, ya que admite distintos formatos tanto en los datos de petición como de respuesta: HTML, CSV, JSON, XML, imágenes, PDFs, audio, video…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0d-aCRMN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AdsEIG1WHGFgoxDHEpEk_Wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0d-aCRMN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AdsEIG1WHGFgoxDHEpEk_Wg.png" alt="Esquema del protocolo HTTP" width="800" height="383"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Esquema del protocolo HTTP&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  URLs
&lt;/h4&gt;

&lt;p&gt;La URL es posiblemente el componente más importante de HTTP, ya que es la cadena que va a representar una dirección. Las siglas URL vienen de &lt;em&gt;Uniform Resource Locator&lt;/em&gt;, o &lt;em&gt;localizador uniforme de recursos&lt;/em&gt; en castellano plano. Como su nombre indica, es un localizador de recursos, una cadena que nos permite identificar un recurso de forma unívoca. Veamos sus partes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--keCIpg2E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AN8wBLpcrp3AfYXPocSloKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--keCIpg2E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AN8wBLpcrp3AfYXPocSloKA.png" alt="Esquema completo de una URL" width="800" height="390"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Esquema completo de una URL&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocolo o esquema:&lt;/strong&gt; esta parte es obligatoria e indica el protocolo o servicio que vamos a utilizar. Puesto que las URLs se usan en otros protocolos, como FTP, SSH, NFS y muchos otros más, indicar el protocolo es imprescindible. Además, cada protocolo tiene definido un puerto por defecto, por lo que si no ha cambiado por algún motivo, podremos ahorrarnos poner el puerto en la URL.
En el caso que nos atañe, el protocolo será HTTP o HTTPS (la versión cifrada del protocolo HTTP).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usuario y contraseña:&lt;/strong&gt; aunque no es muy común, podemos utilizar la propia URL para autenticarnos, aunque a la vista salta de que no es muy seguro. Esto suele utilizarse más en otros protocolos, pero no está de más saber que esto existe.
El usuario y la contraseña se separan mediante el carácter de los &lt;em&gt;dos puntos&lt;/em&gt; o &lt;em&gt;colon&lt;/em&gt;. La arroba (@) se utiliza para separar la contraseña del dominio.
Esta parte es, obviamente, opcional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dominio y TLD:&lt;/strong&gt; el nombre de dominio es la parte más común de una URL e indica el servidor al que queremos conectarnos. Se compone de 3 partes:
  &lt;strong&gt;— Subdominio:&lt;/strong&gt; es opcional. Normalmente indica distintos servicios o funciones dentro de un mismo servidor: www, ftp, api, assets… etc..
&lt;strong&gt; — Dominio:&lt;/strong&gt; es la parte más conocida, el nombre del servidor al que nos conectamos: Google, Amazon, Microsoft…
&lt;strong&gt; — TLD:&lt;/strong&gt; &lt;em&gt;Top Level Domain&lt;/em&gt;, es decir, los ya conocidos .es, .com, .net…
El dominio y el TLD son obligatorios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puerto:&lt;/strong&gt; habitualmente esta parte de la URL va implícita con el protocolo, pero en ocasiones (por ejemplo en desarrollo) es posible que estemos utilizando un puerto distinto para servir nuestro servicio. La manera correcta de indicar el puerto es mediante el carácter de los &lt;em&gt;dos puntos&lt;/em&gt; o &lt;em&gt;colon&lt;/em&gt; y el número de puerto.
Esta parte es opcional, como ya hemos dicho.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruta, &lt;em&gt;path&lt;/em&gt; o URI:&lt;/strong&gt; es la cadena que identifica un recurso dentro del servicio. En ocasiones oiremos que se refieren a ella como &lt;em&gt;URI (Universal Resource Identifier)&lt;/em&gt; o &lt;em&gt;path&lt;/em&gt;. Habitualmente es una cadena separada por barras que indica la ubicación de un recurso.
Esta parte es obligatoria, aunque si no la incorporamos se asume que estamos accediendo a la raíz, representada por la barra /.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anclaje, &lt;em&gt;anchor&lt;/em&gt; o &lt;em&gt;fragment&lt;/em&gt;:&lt;/strong&gt; esto solo tiene sentido dentro del contexto de la web (HTML para ser más exactos). Se utiliza para indicar a qué sección dentro de un documento queremos hacer referencia con la URL.
Es totalmente opcional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parámetros o &lt;em&gt;query string:&lt;/em&gt;&lt;/strong&gt; es un conjunto de variables que le pasamos la URL. Habitualmente con la intención de parametrizar la respuesta, como, por ejemplo, en el caso de usar paginación. Para indicar que empezamos a pasar parámetros se usa el carácter &lt;em&gt;?&lt;/em&gt;, y para separar un parámetro de otro se usa el carácter &lt;em&gt;&amp;amp;&lt;/em&gt;.
Esto es totalmente opcional.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Peticiones&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Como su nombre indica, una petición es el acto de requerir a un servicio que realice cierta acción y nos responda con el resultado.&lt;/p&gt;

&lt;p&gt;En el caso de las peticiones HTTP, estas se componen de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verbo:&lt;/strong&gt; indica el tipo de acción a realizar, lo veremos en profundidad más adelante.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL:&lt;/strong&gt; ruta a la que estamos solicitando la acción.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cabeceras:&lt;/strong&gt; son unos parámetros que nos dan información sobre la propia petición o sus requisitos. Podemos, por ejemplo, especificar en qué formato queremos la respuesta o en qué idioma. Mas adelante entraremos en profundidad sobre este tema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cuerpo:&lt;/strong&gt; en el caso de las peticiones de escritura, aquí es donde va el contenido de nuestra petición. Puede estar en distintos formatos, pero tenemos que especificar mediante una cabecera qué formato hemos utilizado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Respuestas&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Como contraparte a una petición, tenemos la respuesta. La respuesta sigue un formato muy similar a la petición, solo que en este caso no incorpora un verbo, pero sí un &lt;em&gt;código de estado&lt;/em&gt; (status code) que define el resultado de la petición. Obviamente, la respuesta sigue incluyendo un cuerpo con los datos que hayamos solicitado o información extra, el código de estado es una forma de &lt;em&gt;clasificar la respuesta&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Veamos qué elementos componen una respuesta HTTP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Código de estado (status code):&lt;/strong&gt; indica el tipo de respuesta. Entraremos en detalle más adelante.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cabeceras:&lt;/strong&gt; son unos parámetros que nos dan información sobre la propia respuesta, como por ejemplo su formato, idioma, dirección del nuevo recurso creado u otras relacionadas con la caché.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cuerpo:&lt;/strong&gt; en el caso de las respuesta a peticiones de lectura, aquí es donde va el contenido solicitado. Puede estar en distintos formatos, pero tenemos que especificar mediante una cabecera qué formato hemos utilizado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cabeceras
&lt;/h4&gt;

&lt;p&gt;Como ya hemos comentado, las cabeceras son tanto parte de las peticiones como de las respuestas, y éstas sirven tanto para aportar información de las mismas, como para configurarlas. Por ejemplo, mediante cabeceras de petición podemos indicarle al servidor qué formato de respuestas queremos (&lt;em&gt;Accept&lt;/em&gt;), o en qué idioma (&lt;em&gt;Locale&lt;/em&gt;), en qué formato estamos enviando datos (&lt;em&gt;Content-Type&lt;/em&gt;), de dónde venimos (&lt;em&gt;Referrer&lt;/em&gt;) o incluso quiénes somos (&lt;em&gt;Auth&lt;/em&gt;) y qué cliente usamos (&lt;em&gt;User-Agent&lt;/em&gt;). Con las respuestas podemos hacer lo mismo, e incluir, además, información acerca del servidor (&lt;em&gt;Server&lt;/em&gt;), la compresión utilizada (&lt;em&gt;Content-Enconding&lt;/em&gt;), la cache (&lt;em&gt;Cache-*&lt;/em&gt;) y un largo etcétera.&lt;/p&gt;

&lt;p&gt;Las archiconocidas cookies también se incluyen en las cabeceras, tanto de las respuestas como de las peticiones.&lt;/p&gt;

&lt;p&gt;Si nos quedamos cortos de cabeceras para lo que necesitamos, siempre podemos definir nuestra propias cabeceras prefijando X- al nombre de nuestra cabecera (aunque es una práctica desaconsejada).&lt;/p&gt;

&lt;p&gt;Podemos consultar una lista de todas las cabeceras disponibles en &lt;a href="https://en.wikipedia.org/wiki/List_of_HTTP_header_fields"&gt;&lt;strong&gt;Wikipedia — List of HTTP headers&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Códigos de estado&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Los códigos de estado son unos valores numéricos incluidos en las respuestas que nos ayudan a determinar si la respuesta ha sido exitosa, fallida por culpa de la petición o fallida por culpa del servicio.&lt;/p&gt;

&lt;p&gt;Los códigos de estado se agrupan en 5 bloques:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ROIBaZXU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AXRJVAcktocO2vrjhzx14kg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ROIBaZXU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AXRJVAcktocO2vrjhzx14kg.png" alt="División en grupos de los códigos de estado" width="800" height="590"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;División en grupos de los códigos de estado&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Como se puede apreciar en el gráfico de arriba, estos 5 bloques de códigos de estado se diferencian por el primer dígito, que es el que indica que tipo de respuesta hemos obtenido. Los siguientes dos dígitos nos aportan información más específica sobre la respuesta. Vamos a ver algunos ejemplos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1xx Informacionales&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 Continue&lt;/li&gt;
&lt;li&gt;101 Switching Protocols&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2xx Éxito&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 OK&lt;/li&gt;
&lt;li&gt;201 Created&lt;/li&gt;
&lt;li&gt;202 Accepted&lt;/li&gt;
&lt;li&gt;204 No Content&lt;/li&gt;
&lt;li&gt;206 Partial Content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3xx Redirection&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;301 Moved Permanently&lt;/li&gt;
&lt;li&gt;302 Found&lt;/li&gt;
&lt;li&gt;304 Not Modified&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4xx Error de Cliente&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;400 Bad Request&lt;/li&gt;
&lt;li&gt;401 Unauthorized&lt;/li&gt;
&lt;li&gt;402 Payment Required&lt;/li&gt;
&lt;li&gt;403 Forbidden&lt;/li&gt;
&lt;li&gt;404 Not Found&lt;/li&gt;
&lt;li&gt;405 Method Not Allowed&lt;/li&gt;
&lt;li&gt;409 Conflict&lt;/li&gt;
&lt;li&gt;412 Precondition Failed&lt;/li&gt;
&lt;li&gt;413 Request Entity Too Large&lt;/li&gt;
&lt;li&gt;415 Unsupported Media Type&lt;/li&gt;
&lt;li&gt;422 Unprocessable Entity&lt;/li&gt;
&lt;li&gt;428 Precondition Required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5xx Error de Servidor&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;500 Internal Server Error&lt;/li&gt;
&lt;li&gt;501 Not Implemented&lt;/li&gt;
&lt;li&gt;502 Bad Gateway&lt;/li&gt;
&lt;li&gt;503 Service Unavailable&lt;/li&gt;
&lt;li&gt;504 Gateway Timeout&lt;/li&gt;
&lt;li&gt;505 HTTP Version Not Supported&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se puede consultar una lista más completa en este enlace: &lt;a href="https://www.restapitutorial.com/httpstatuscodes.html"&gt;RestApiTutorial — Status Codes&lt;/a&gt; o en &lt;a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes"&gt;Wikipedia — Status Codes&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Verbos
&lt;/h4&gt;

&lt;p&gt;Ahora que ya hemos hablado de las URLs vamos a ver cómo interactuar con ellas. El protocolo HTTP se sirve de un conjunto de &lt;em&gt;verbos&lt;/em&gt; o acciones que se deben de utilizar en función del tipo de petición que queramos llevar a cabo, como, por ejemplo, una lectura de datos o una escritura.&lt;/p&gt;

&lt;p&gt;Vamos a ver los verbos más comunes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GET.&lt;/strong&gt; Se usa para leer contenidos. Es muy habitual que las URLs consultadas mediante GET admitan parámetros de &lt;em&gt;query string.&lt;/em&gt; Estas peticiones carecen de cuerpo de petición.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;POST.&lt;/strong&gt; Esta es la petición que se utiliza para crear nuevos recursos. Es la única operación no &lt;em&gt;idempotente&lt;/em&gt;, es decir, si la ejecutamos más de una vez, el estado de nuestro sistema habrá cambiado (habremos creado dos recursos), algo que no sucede con el resto de verbos. Es por esto, entre otras cosas, que las peticiones POST no pueden ser cacheadas.
Las peticiones POST tienen cuerpo o body, y es ahí donde va la información que utilizaremos para escribir el nuevo recurso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PUT.&lt;/strong&gt; Al igual que POST, esta petición escribe datos, pero en este caso para actualizar un recurso de forma completa, es decir, reemplazar su contenido por el que viene en el body o cuerpo de la petición.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DELETE.&lt;/strong&gt; Es el verbo que utilizamos cuando queremos eliminar un recurso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PATCH.&lt;/strong&gt; Es similar a PUT, pero a diferencia de PUT no reemplaza el recurso por completo, sino que sólo lo modifica parcialmente. Es necesario especificar un formato de petición que indique los cambios que van a realizarse sobre el recurso. Actualmente no hay un estándar para ello y es un verbo poco utilizado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HEAD.&lt;/strong&gt; Hay ocasiones en las que solo nos interesa conocer el resultado de una petición GET sin ver su contenido. Con el verbo HEAD podemos obtener solo el código de estado de una petición. Esto puede ser útil, por ejemplo, para determinar si un recurso existe o no sin necesidad de obtenerlo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPTIONS.&lt;/strong&gt; Este verbo nos permite conocer de una URL que verbos admite, es decir, si podemos realizar GET, POST y PUT, o solamente POST, o solamente GET o cualquier combinación posible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Otros aspectos de un API HTTP
&lt;/h3&gt;

&lt;p&gt;Una de las principales características de las APIs que hemos mencionado antes es que son multimedia y eso quiere decir que admite distintos formatos tanto en los datos de petición como de respuesta: HTML, CSV, JSON, XML, imágenes, PDFs, audio, video…&lt;/p&gt;

&lt;p&gt;Veamos algunos ejemplos.&lt;/p&gt;

&lt;h4&gt;
  
  
  Formatos de petición
&lt;/h4&gt;

&lt;p&gt;Las peticiones suelen seguir formatos de entrada simples, habitualmente JSON o XML, aunque perfectamente podría ser YAML, TOML, CSV o cualquier tipo de fichero.&lt;/p&gt;

&lt;p&gt;La ventaja de JSON o XML es que son formatos suficientemente estructurados como para representar la información de una manera relativamente comprensible para una persona y fácilmente procesable para una máquina.&lt;/p&gt;

&lt;p&gt;El formato de la petición se indica en la cabecera &lt;em&gt;Content-Type&lt;/em&gt;, y esto es importante para que al procesarse la petición el &lt;em&gt;backend&lt;/em&gt; sepa cómo procesar los datos de entrada.&lt;/p&gt;

&lt;p&gt;En caso de que se utilice el formato XML, dado que es un metalenguaje que permite especificar distintos esquemas, es imprescindible que este incluya el esquema usado para indicar al &lt;em&gt;backend&lt;/em&gt; como interpretar la entrada.&lt;/p&gt;

&lt;p&gt;Si lo que queremos es adjuntar archivos, estos deben de ir codificados. Habitualmente se usa la codificación &lt;em&gt;base64,&lt;/em&gt; aunque cualquier tipo de codificación podría ser válido siempre y cuando se indique en alguna cabecera como &lt;em&gt;Content-Encoding&lt;/em&gt; el algoritmo de codificación. Recordemos que la codificación es un proceso reversible que consiste en &lt;em&gt;traducir&lt;/em&gt; de un formato a otro, algoritmos de &lt;em&gt;hashing&lt;/em&gt; como MD5 o SHA1 no servirían.&lt;/p&gt;

&lt;h4&gt;
  
  
  Formatos de respuesta
&lt;/h4&gt;

&lt;p&gt;Para el formato de las respuestas existen una serie de estándares que nos permiten desarrollar clientes de una forma más sencilla. Veamos algunos de ellos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jsonapi.org/format/"&gt;&lt;strong&gt;JSON-API&lt;/strong&gt;&lt;/a&gt;
JSON-API es un formato documentado de respuestas para APIs. Explicarlo con detalle daría pie a un post entero dedicado a ello, por lo que solo comentaremos una serie de detalles. Suele componerse de una serie de &lt;em&gt;top-level elements&lt;/em&gt; o elementos raíz, por ejemplo &lt;em&gt;links&lt;/em&gt;, con toda la información relativa a la paginación en caso de estar devolviendo listas de recursos. Otro elemento imprescindible es &lt;em&gt;data&lt;/em&gt;, que puede ser a su vez un objeto de tipo &lt;em&gt;resource object&lt;/em&gt; o un array de este tipo de objetos (si la respuesta es una colección).
Si la petición ha resultado fallida no contendrá ninguno de estos elementos, y en su lugar tendrá un elemento &lt;em&gt;errors&lt;/em&gt; con los errores que se han producido.
Recomiendo echar un vistazo a la especificación completa con ejemplos en la web oficial, se pueden encontrar los enlaces en la sección de Bibliografía o el enlace al inicio de esta sección.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-00"&gt;&lt;strong&gt;HAL&lt;/strong&gt;&lt;/a&gt;
Este formato en realidad no ha llegado a pasar la fase de borrador o &lt;em&gt;draft&lt;/em&gt;, por lo que se pueden encontrar implementaciones, pero no se garantiza su soporte o compatibilidad. En muchos aspectos es muy similar a JSON-API.
Podría decirse que JSON-API usó de base JSON-HAL para definir su formato.
De nuevo, recomiendo echar un vistazo a la especificación completa con ejemplos en el &lt;em&gt;draft&lt;/em&gt;, se pueden encontrar los enlaces en la sección de Bibliografía o el enlace al inicio de esta sección.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Hemos dado un repaso a varias de las características principales de las APIs HTTP, es buen momento para dejarlo aquí y reflexionar sobre lo aprendido y observar nuestras propias APIs y pensar en cómo podemos mejorarlas.&lt;/p&gt;

&lt;p&gt;Esta serie de posts seguirá abierta, en breve hablaremos de algunos tipos de APIs, como REST, RESTful, GraphQL… hablaremos de temas accesorios pero no por ello menos importantes, como autenticación, seguridad, serialización, documentación, versionado…&lt;/p&gt;

&lt;p&gt;Esperamos que todo este conocimiento que hemos ido recopilando os sea de utilidad y sigáis leyendo el resto de la serie!&lt;/p&gt;

&lt;h3&gt;
  
  
  En próximos posts…
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@mangelsnc/apis-rest-c16a54a25aa8"&gt;APIs REST&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;APIs GraphQL&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mangelsnc.medium.com/8bf2be3a8e4"&gt;Autenticación y gestión de la sesión&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@mangelsnc/documentar-apis-98f0101b62b8"&gt;Documentación de APIs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bibliografia
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3xjp6Rw"&gt;RESTful Web APIs: Services for a Changing World&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leanpub.com/introduccion_apis_rest"&gt;Principios de diseño de APIs REST&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jsonapi.org/format/"&gt;Especificación JSON-API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-00"&gt;Draft especificación JSON-HAL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>graphql</category>
      <category>restapi</category>
      <category>api</category>
      <category>apidevelopment</category>
    </item>
    <item>
      <title>Estrategias de migración: Strangler Fig Application y Anticorruption Layer</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Thu, 29 Jul 2021 07:41:01 +0000</pubDate>
      <link>https://dev.to/mangelsnc/estrategias-de-migracion-strangler-fig-application-y-anticorruption-layer-2khf</link>
      <guid>https://dev.to/mangelsnc/estrategias-de-migracion-strangler-fig-application-y-anticorruption-layer-2khf</guid>
      <description>&lt;h3&gt;
  
  
  Estrategias de migración de legacy code: Strangler Fig Application y Anticorruption Layer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pFJigdiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AVfS2OhK1xloVv9zsDEgeDw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pFJigdiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AVfS2OhK1xloVv9zsDEgeDw.jpeg" alt="" width="800" height="450"&gt;&lt;/a&gt;Ficus Estrangulador Australiano&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducción
&lt;/h3&gt;

&lt;p&gt;Si hay algo por lo que todos pasamos alguna vez, es por heredar y mantener un proyecto. Puede ser un proyecto antiguo de nuestra empresa, un proyecto que ha llegado de un cliente descontento con su anterior proveedor… etc. El mayor problema que esto supone es que habitualmente nos encontramos con proyectos desarrollados en tecnologías antiguas o desactualizadas, poco mantenidos, con un estilo o unas prácticas que no nos acaban de gustar (los programadores somos todos un poco especialitos en esto) y lo peor de todo: sin tests.&lt;/p&gt;

&lt;p&gt;La palabra que siempre nos ronda a la cabeza cuando tratamos con estos proyectos heredados es “legacy code”, que como bien dijo Michael Feathers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Legacy code is code without tests&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Michael Feathers — Working effectively with legacy code&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En realidad es mucho más que eso (que no es poco), ya que suelen ser proyectos poco o mal documentados (los tests son siempre la mejor documentación), con versiones de lenguajes, frameworks y librerías anticuadas u obsoletas, y muchas veces difíciles de volver a encarrilar, ya que se basan en prácticas poco amigables para con el testing o el refactoring. En pocas palabras: &lt;strong&gt;acumulan una gran deuda técnica.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Otro factor importante es que el proyecto suele ser la fuente de ingresos de una empresa que no puede permitirse el lujo de para máquinas de forma indefinida (&lt;a href="https://www.reddit.com/r/programming/comments/iulp4q/evernote_spent_18_months_fixing_their_tech_debt/"&gt;como en su momento hiciera Evernote&lt;/a&gt;) para limpiar toda la deuda técnica y replantear los cimientos de su fuente de ingresos.&lt;/p&gt;

&lt;p&gt;Si los grandes refactors muchas veces se descartan, la reescritura es algo que solo se suele plantear el equipo técnico (a veces desde un punto de vista poco empático de cara al cliente).&lt;/p&gt;

&lt;p&gt;Otras veces el problema no es el tanto el código sino que debemos de construir un software sobre una fuente de datos que puede no encajar de la mejor forma con nuestro proyecto. O con un diseño pobre que puede ser mejorado, pero que requiere un gran esfuerzo y dedicación y que solo tras demostrar que el nuevo enfoque es mejor, el cliente estaría dispuesto a aceptar el cambio.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ante estas situaciones ¿qué opciones tenemos?
&lt;/h4&gt;

&lt;p&gt;En mi experiencia muchas veces se ha optado por mantener el proyecto legacy y o bien por presiones del equipo de desarrollo, por la dificultad para contratar a gente que se haga cargo del proyecto en el estado en que se encuentra o por problemas de crecimiento debidos al estado del proyecto, se ha optado por abordar una &lt;strong&gt;migración progresiva.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Esto no es otra cosa que empezar a desarrollar nuevas partes del proyecto sobre un stack moderno y con mejores prácticas, pero sin dejar de depender del antiguo proyecto. Estas migraciones pueden durar eternamente, pero suelen insuflar nueva vida a un proyecto que estaba agonizando, y con una buena planificación es posible dejar de depender del antiguo proyecto a medio plazo.&lt;/p&gt;

&lt;p&gt;Me gustaría hoy hablar de dos estrategias de migraciones progresivas sobre los que me he apoyado cuando he tenido que abordar este tipo de tareas: &lt;em&gt;Strangle Fig&lt;/em&gt; y &lt;em&gt;Anticorruption Layer.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Strangler Fig Application (Ficus Estrangulador)
&lt;/h3&gt;

&lt;p&gt;Este estrategia fue propuesta por Martin Fowler en 2004. Aunque inicialmente se llamó &lt;em&gt;Strangler Application&lt;/em&gt;, posteriormente fue renombrado a &lt;em&gt;StranglerFigApplication&lt;/em&gt; en 2009 para evitar la connotación negativa de la palabra &lt;em&gt;Strangler&lt;/em&gt; (estrangulador):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://martinfowler.com/bliki/StranglerFigApplication.html"&gt;bliki: StranglerFigApplication&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esta técnica de migración consiste en interponer una fachada entre el cliente y el sistema a migrar. De puertas para adentro, empezaremos a migrar progresivamente partes del proyecto &lt;em&gt;legacy&lt;/em&gt; a el nuevo sistema, y será la fachada la que se encargará de redirigir el cliente al nuevo o al viejo sistema según sea necesario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q29PpCNS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AnvOPuOuISQcys_VmMj4AQQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q29PpCNS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AnvOPuOuISQcys_VmMj4AQQ.png" alt="" width="800" height="189"&gt;&lt;/a&gt;Migración progresiva de un proyecto legacy a un nuevo sistema&lt;/p&gt;

&lt;p&gt;Esto nos va a permitir realizar una migración sin la presión de tener que “parar máquinas” y dejar el proyecto en stand-by, permitiéndonos priorizar la migración de las partes más críticas sin importar sus dependencias, ya que las podremos satisfacer contra el sistema legacy.&lt;/p&gt;

&lt;p&gt;No todo son ventajas, por supuesto. El uso de esta estrategia puede incrementar los tiempos de respuesta mientras dure la migración, así como los costes de infraestructura, ya que al menos necesitaremos separar el sistema legacy del nuevo, además de tener una capa encargada de la distribución. Aún así, es preferible esto a dejar nuestro proyecto estancado.&lt;/p&gt;

&lt;p&gt;Esta estrategia está siendo adoptada por frameworks como Symfony para facilitar las &lt;a href="https://symfony.com/doc/current/migration.html#front-controller-with-legacy-bridge"&gt;migraciones desde otros frameworks&lt;/a&gt;. Además, existen &lt;a href="https://paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies/"&gt;numerosos casos de éxito documentados&lt;/a&gt; que han seguido esta práctica.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anticorruption Layer
&lt;/h3&gt;

&lt;p&gt;La siguiente estrategia o patrón que vamos a ver es la &lt;em&gt;Anticorruption Layer&lt;/em&gt; (abreviado como ACL) propuesta por Eric Evans en su libro &lt;a href="https://paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies/"&gt;Domain-Driven Design: Tackling complexity in the heart of software&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Básicamente, la ACL es una capa que se encargará de &lt;strong&gt;traducir entre el modelo de datos legacy y el nuevo modelo de datos.&lt;/strong&gt; Es muy similar en misión al patrón adapter, &lt;a href="https://dev.to/mangelsnc/una-interfaz-para-controlarlos-a-todos-patron-adapter-46o1"&gt;del cual ya hablamos en su momento&lt;/a&gt;, pero aplicado a datos en este caso.&lt;/p&gt;

&lt;p&gt;Pero no solo eso, sino que además, esta capa puede implementar también algunas comprobaciones de seguridad, devolver valores por defecto en caso de no existir en el sistema original, lanzar excepciones más específicas para casos de error o incluso implementar un &lt;em&gt;circuit-breaker&lt;/em&gt; si el problema se debe a la disponibilidad del servicio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BFieS0G7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AiWfP9XrFkqDpXlLbrgnWdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BFieS0G7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AiWfP9XrFkqDpXlLbrgnWdg.png" alt="" width="800" height="516"&gt;&lt;/a&gt;Comunicación entre sistemas legacy y modernos a través de una ACL.&lt;/p&gt;

&lt;h4&gt;
  
  
  ¿Cuándo usar Anticorruption Layer?
&lt;/h4&gt;

&lt;p&gt;Podemos ver la respuesta en palabras de el propio Eric Evans:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your application needs to deal with a database or another application whose model is undesirable or inapplicable to the model you want within your own application, use an &lt;a href="http://wiki.c2.com/?AnticorruptionLayer"&gt;Anticorruption Layer&lt;/a&gt; to translate to/from that model and yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Eric Evans — Domain-Driven Design: Tackling complexity in the heart of software&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O en palabras de Vaughn Vernon, autor de &lt;a href="https://amzn.to/3f8jbFh"&gt;&lt;em&gt;Implementing Domain-Driven Design&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even if you are able to avoid creating a Big Ball of Mud by employing DDD techniques, you may still need to integrate with one or more. If you must integrate with one or more, try to create an Anticorruption Layer against each legacy system in order to protect your own model from the cruft that would otherwise pollute your model with the incomprehensible morass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Vaughn Vernon — Domain-Driven Design Distilled&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es decir, siempre que necesitamos que nuestro sistema &lt;em&gt;hable&lt;/em&gt; con otro sistema cuyo modelo de datos no es el deseado, o incluso si estamos heredando una base de datos sobre la que construir un nuevo proyecto, podemos usar una ACL para &lt;em&gt;traducir&lt;/em&gt; del viejo modelo al nuevo evitando que el legacy &lt;em&gt;contamine&lt;/em&gt; nuestro proyecto.&lt;/p&gt;

&lt;h4&gt;
  
  
  Casos de uso de ACL
&lt;/h4&gt;

&lt;p&gt;Esta técnica es ampliamente utilizada en arquitecturas de microservicios donde existen distintas versiones de las APIs de comunicación e incluso de los modelos de datos (recordemos que cada microservicio tiene su propia base de datos con su propio esquema).&lt;/p&gt;

&lt;p&gt;Un problema que puede derivar de la práctica de la migración mediante &lt;em&gt;StranglerFigApplication&lt;/em&gt; es que en ocasiones será necesario que exista comunicación entre el proyecto legacy y el nuevo, por lo que el uso de esta técnica combinada con la anterior es más que recomendable.&lt;/p&gt;

&lt;p&gt;Otro caso de uso que para el que he aplicado personalmente esta estrategia ha sido para lidiar con bases de datos NoSQL que tienen en una misma colección documentos con distinto esquema. Es especialmente útil el uso de una ACL que homogeneice el esquema de todos los documentos para que encajen adecuadamente con los objetos del dominio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Aunque puede resultar tentador proponer una reescritura entera de un proyecto desfasado, es importante valorar nuestras opciones antes. No siempre va a ser posible abordar este tipo de proyectos, pero debemos de conocer qué otras alternativas tenemos.&lt;/p&gt;

&lt;p&gt;Esto es solo una muestra de un par de estrategias que personalmente me han resultado útiles en el pasado, pero no son las únicas, en un futuro hablaremos de otras.&lt;/p&gt;

&lt;p&gt;Saludos!&lt;/p&gt;




</description>
      <category>designpatterns</category>
      <category>ddd</category>
      <category>legacycode</category>
      <category>acl</category>
    </item>
    <item>
      <title>Microservicios</title>
      <dc:creator>Miguel Ángel Sánchez Chordi</dc:creator>
      <pubDate>Mon, 06 Jul 2020 07:01:01 +0000</pubDate>
      <link>https://dev.to/mangelsnc/microservicios-4iph</link>
      <guid>https://dev.to/mangelsnc/microservicios-4iph</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--je0u3AxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AJmORH_N5-yxBinWnbJaMiA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--je0u3AxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AJmORH_N5-yxBinWnbJaMiA.jpeg" alt="" width="800" height="533"&gt;&lt;/a&gt;Foto por &lt;a href="https://unsplash.com/@vivekdoshi"&gt;Vivek Doshi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguro que en los últimos años has oído hablar del concepto de microservicios, puede que hayas profundizado en el tema, o incluso llegado a trabajar en algún proyecto en base a microservicios, pero para la mayoría sigue siendo un tema del que muchos hablan pero pocos se han pasado por las manos.&lt;/p&gt;

&lt;p&gt;Como cualquier otra tecnología que cobra relevancia, tiene sus defensores y sus detractores, cada uno con su línea de argumentación (totalmente válida). El caso es que existe y que no sea una solución para nuestro proyecto o nuestros proyectos del día a día, no quiere decir que no tenga su caso de uso.&lt;/p&gt;

&lt;p&gt;En este post vamos a intentar explicar en líneas generales en qué consiste la arquitectura de microservicios, sus pros, sus contras, problemas conocidos y distintas formas de comunicación. No pretende ser una guía exhaustiva, por lo que no voy a tratar en profundidad demasiados conceptos.&lt;/p&gt;

&lt;p&gt;Vamos allá!&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducción
&lt;/h3&gt;

&lt;p&gt;Habitualmente abreviado como MSA (&lt;em&gt;Micro Services Architecture&lt;/em&gt;), es una variación de SOA o &lt;a href="https://es.wikipedia.org/wiki/Arquitectura_orientada_a_servicios"&gt;Arquitectura Orientada a Servicios&lt;/a&gt; (&lt;em&gt;Service Oriented Architecture&lt;/em&gt;), y aunque parezca algo totalmente nuevo y actual, se viene hablando, escribiendo y poniendo en práctica desde &lt;a href="https://www.gartner.com/resources/114300/114358/114358.pdf"&gt;1996&lt;/a&gt; (Gartner).&lt;/p&gt;

&lt;p&gt;Aunque no sería hasta 2005 cuando Peter Rodgers acuñaría el termino &lt;em&gt;Micro-Web Services&lt;/em&gt; durante una presentación en la &lt;em&gt;Web Services Edge conference.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Desde entonces, muchos han sido los que han hablado o escrito sobre el tema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/microservices.html"&gt;Martin Fowler y James Lewis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/30kRYc1"&gt;Sam Newman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/2ALKkN5"&gt;Chris Richardson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3dFeQqm"&gt;Matthias Noback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3dFH8AW"&gt;Ronnie Mitra&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y una lista casi infinita de expertos reconocidos. Pero ¿en qué consiste una arquitectura de microservicios? ¿Qué características tiene?&lt;/p&gt;

&lt;p&gt;Básicamente, una arquitectura de microservicios consiste en construir una aplicación como un conjunto de pequeños servicios, independientes entre ellos tanto a nivel código como a nivel de infraestructura y que se comunican entre ellos con mecanismos ligeros (baja latencia).&lt;/p&gt;

&lt;p&gt;Cada servicio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gestiona una parte de negocio única y exclusivamente&lt;/li&gt;
&lt;li&gt;Debe poder desplegarse y escalarse de forma independiente sin tener esto efecto sobre el resto de servicios&lt;/li&gt;
&lt;li&gt;Puede estar escrito con el lenguaje que mejor se adapte a su propósito, así como usar las tecnologías más convenientes (por ejemplo, bases de datos no-SQL cuando el resto de microservicios usan SQL).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ventajas
&lt;/h4&gt;

&lt;p&gt;Teniendo en cuenta la anterior descripción, no son pocas las ventajas que nos aporta esta arquitectura:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desarrollo modular:&lt;/strong&gt; Cada servicio tiene una única meta, esto hace que su responsabilidad quede claramente acotada y su equipo de desarrollo puede especializarse en ello, sin interferencias de cambios en otros aspectos del negocio. &lt;a href="https://medium.com/all-you-need-is-clean-code/principio-de-%C3%BAnica-responsabilidad-srp-c67c3626ff47"&gt;Es una especie de SRP a nivel módulo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independencia de infraestructura:&lt;/strong&gt; Los módulos pueden y deben seguir su propio ciclo de vida, desplegarse nuevas versiones cuando sea necesario (sin conflictos o necesidad de esperar a otros). Asimismo, cada microservicio es responsable de su propia infraestructura, incluyendo su propia base de datos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalado independiente:&lt;/strong&gt; En un escenario donde tenemos un monolito y de repente tenemos un incremento bestial de un tipo de peticiones en concreto (registros por ejemplo, debido a una agresiva campaña de marketing), nuestra única solución va a ser escalar todo el proyecto a la vez, bien sea de forma vertical (añadiendo o mejorando el hardware) o si hemos sido suficientemente prudentes de tener separada la base de datos y otros servicios en otras maquinas, un escalado horizontal (aumentar el número de servers con servidores web y poner un balanceador de carga al frente). En un sistema basado en microservicios simplemente necesitas escalar de forma horizontal el número de servers que sirven el microservicio de usuarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimización del esquema de datos:&lt;/strong&gt; La independencia de infraestructura, permite que en nuestros modelos de datos guardemos únicamente lo imprescindible para lograr nuestro objetivo. Si por ejemplo disponemos de un microservicio de &lt;em&gt;Posts&lt;/em&gt; y uno de &lt;em&gt;Users&lt;/em&gt;, podemos guardar en la base de datos de &lt;em&gt;Users&lt;/em&gt; tan solo un contador con el número de posts (si solo necesitamos ese dato), y en la base de datos de &lt;em&gt;Posts&lt;/em&gt; nos podemos permitir almacenar solamente el id, nombre y apellidos de cada &lt;em&gt;User&lt;/em&gt;, ya que no vamos a necesitar nada más en nuestras vistas. Resultado: &lt;strong&gt;prácticamente resolvemos todas las consultas a base de datos sin hacer JOIN, consultas directas a índice.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independencia de stack:&lt;/strong&gt; Pueden desarrollarse con el lenguaje que mejor encaje en el problema a resolver, sin tener en cuenta en cuál (o cuáles) se ha desarrollado el resto de microservicios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Inconvenientes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desarrollo más complejo:&lt;/strong&gt; A medida que el número de microservicios crece, levantar un entorno de desarrollo para cada equipo es más complicado. Además, el debug de estas arquitecturas es bastante más complejo que el de un monolito.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versionado de microservicios:&lt;/strong&gt; La independencia de cada microservicio puede llegar a ser un caos si no se versiona correctamente, ya que puede haber otros microservicios dependientes de uno que se acaba de actualizar que aún no sea compatible con los nuevos cambios, y eso nos obliga a mantener distintas versiones de cada microservicio en marcha que garantice el funcionamiento de todo el enjambre.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Información duplicada:&lt;/strong&gt; Gran parte de la información estará duplicada en las distintas bases de datos de los distintos microservicios, ya que cada uno debe de ser independiente a nivel datos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistencia eventual:&lt;/strong&gt; Las actualizaciones pueden ser un quebradero de cabeza, por ejemplo, si el usuario decide actualizar su nombre y apellidos, ya que en el microservicio de &lt;em&gt;Posts&lt;/em&gt; deberemos de actualizar este dato en todos sus posts. Esto puede dar lugar a problemas de consistencia eventual debido a la latencia entre comunicaciones (el dato se ha actualizado en algunos servicios, pero no en otros).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Arquitectura de microservicios
&lt;/h3&gt;

&lt;p&gt;Como convención, vamos a hablar de diseño de “microarquitectura” cuando nos refiramos a la arquitectura interna de cada microservicio, y diseño de “macroarquitectura” cuando nos refiramos a la arquitectura que los une.&lt;/p&gt;

&lt;p&gt;Veamos a continuación algunos detalles a cada nivel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detalles de diseño a nivel microarquitectura
&lt;/h3&gt;

&lt;p&gt;La construcción interna de los microservicios no está atada a ningun contrato, ya que como hemos repetido varias veces, cada microservicio es independiente de los demás a nivel infraestructura y a nivel stack tecnológico, pero lo que si es cierto es que hay una serie de técnicas y patrones de diseño que favorecen mucho el mantenimiento de estos, y que al mismo tiempo simplificará en algunos casos la comunicación entre ellos.&lt;/p&gt;

&lt;h4&gt;
  
  
  Arquitectura Hexagonal
&lt;/h4&gt;

&lt;p&gt;Hemos hablado de arquitectura hexagonal en otras ocasiones, aunque quizá sea interesante dedicar un post entero a tratar el tema, pero para no desviar la atención del tema principal, haré un pequeño resumen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--42vMMNrM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/558/1%2AW36o3XNquxpqM3vHnfyyTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--42vMMNrM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/558/1%2AW36o3XNquxpqM3vHnfyyTg.png" alt="" width="558" height="587"&gt;&lt;/a&gt;He usado círculos para hablar de arquitectura hexagonal? He usado círculos para hablar de arquitectura hexagonal.&lt;/p&gt;

&lt;p&gt;La arquitectura hexagonal o también llamada arquitectura limpia (de &lt;a href="https://amzn.to/2YcMUDx"&gt;&lt;em&gt;Clean Architecture&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt; es una forma de diseñar software por capas haciendo un uso del también conocido &lt;a href="https://dev.to/mangelsnc/una-interfaz-para-controlarlos-a-todos-patron-adapter-46o1"&gt;patrón adapter&lt;/a&gt;. La arquitectura por capas favorece la cambiabilidad de las dependencias de terceros sin afectar a las capas dependientes (&lt;a href="https://medium.com/all-you-need-is-clean-code/inversi%C3%B3n-de-dependencias-dip-b8a07b42f99e"&gt;inversión de dependencias&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Tenemos tres capas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dominio&lt;/li&gt;
&lt;li&gt;Aplicación&lt;/li&gt;
&lt;li&gt;Infraestructura&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada una de las capas solo puede conocer a las más internas, es decir, siempre de fuera hacia adentro. Por lo tanto, Infraestructura conoce Aplicación y Dominio, Aplicación conoce a Dominio, y Dominio solo se conoce a sí misma.&lt;/p&gt;

&lt;p&gt;Y qué es cada capa?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dominio&lt;/strong&gt; contiene únicamente el código relativo a entidades, &lt;a href="https://dev.to/mangelsnc/value-objects-1gd9"&gt;&lt;em&gt;value objects&lt;/em&gt;&lt;/a&gt;, interfaces de servicios… básicamente los contratos que deberá de cumplir el código. En otros contextos lo podemos relacionar con el &lt;em&gt;core&lt;/em&gt; de una aplicación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infraestructura&lt;/strong&gt; son las implementaciones de los contratos definidos en &lt;strong&gt;Dominio.&lt;/strong&gt; Por ejemplo, si tenemos una interfaz del servicio de repositorio UserRepository, en infraestructura podemos tener distintas implementaciones del mismo, por ejemplo RedisUserRepository_,_ DoctrineUserRepository_,_ o ElasticSearchUserRepository por citar algunos ejemplos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicación&lt;/strong&gt; contiene la implementación de casos de uso de nuestra aplicación, como por ejemplo Registrar un Usuario o Publicar un Post. Esta capa solo conoce los contratos definidos en &lt;strong&gt;Dominio&lt;/strong&gt; con lo que cualquier implementación de &lt;strong&gt;Infraestructura&lt;/strong&gt; deberá de ser inyectada como una interfaz de &lt;strong&gt;Dominio&lt;/strong&gt;. Así, para por ejemplo Registrar un usuario necesitaríamos un UserRepository, no importa qué implementación, ya que cualquiera de ellas cumplirá con el contrato y sabremos de qué métodos disponemos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Viéndolo de forma gráfica quedaría algo así (fíjate en que cada color que representa la capa a la que pertenece):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bts6VPoD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/959/1%2AYNkUm9nj4AwoHV6Y9jVN7A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bts6VPoD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/959/1%2AYNkUm9nj4AwoHV6Y9jVN7A.png" alt="" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto es &lt;a href="https://medium.com/all-you-need-is-clean-code/inversi%C3%B3n-de-dependencias-dip-b8a07b42f99e"&gt;inversión de dependencias&lt;/a&gt; en estado puro, y es lo que hace que nuestro código sea limpio, cambiable, testeable y fácilmente mantenible.&lt;/p&gt;

&lt;h4&gt;
  
  
  CQRS
&lt;/h4&gt;

&lt;p&gt;Sobre CQRS también podríamos dedicar posts enteros a tratar el tema, pero vamos a tratar de resumirlo de forma simple.&lt;/p&gt;

&lt;p&gt;Bertrand Meyer definió originalmente el concepto de &lt;a href="https://martinfowler.com/bliki/CommandQuerySeparation.html"&gt;Separación de consultas y comandos (CQS)&lt;/a&gt; en el libro &lt;a href="https://amzn.to/3h5oRzj"&gt;&lt;em&gt;Object-Oriented Software Construction&lt;/em&gt;&lt;/a&gt;. La idea básica es que las operaciones de un sistema se pueden dividir en dos categorías claramente diferenciadas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consultas (Queries)&lt;/strong&gt;. Devuelven un resultado sin cambiar el estado del sistema y no tienen efectos secundarios (&lt;em&gt;side effects)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comandos (Command)&lt;/strong&gt;. Cambian el estado de un sistema (y pueden tener &lt;em&gt;side effects)&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Posteriormente Greg Young introdujo el concepto &lt;a href="https://martinfowler.com/bliki/CQRS.html"&gt;Segregación de responsabilidad de consultas y comandos (CQRS)&lt;/a&gt;. Se basa en el principio CQS, aunque con más detalles, por ejemplo, con CQRS se puede tener una base de datos para operaciones de lectura (&lt;em&gt;queries&lt;/em&gt;) distinta de la de operaciones de escritura (&lt;em&gt;commands&lt;/em&gt;), o distintos modelos de datos para las respuestas de las &lt;em&gt;queries&lt;/em&gt; o las peticiones de los &lt;em&gt;commands&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Pero una de las mayores diferencias es la posibilidad de realizar operaciones asíncronas mediante el envío de &lt;em&gt;commands&lt;/em&gt; a través de un bus de comandos asíncrono, de forma que no necesitemos esperar a la respuesta de la base de datos para seguir con el hilo de la ejecución.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;En resumen&lt;/strong&gt; a nuestra infraestructura vamos a incorporar una serie de nuevos elementos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commands:&lt;/strong&gt; Clases que encapsulan operaciones de escritura. Por ejemplo, en el caso de Registrar un usuario este command incluiría el email y la contraseña del usuario registrado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queries:&lt;/strong&gt; Clases que encapsulan operaciones de lectura. Por ejemplo, en el caso de uso Obtener un post la query incluiría el id del post a obtener.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handlers:&lt;/strong&gt; Tendremos QueryHandlers y CommandHandlers, los QueryHandlers devuelven el contenido deseado, los CommandHandlers, debido a que su ejecución puede ser asíncrona, no devuelven nada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buses:&lt;/strong&gt; Tendremos QueryBus y CommandBus, y el CommandBus puede ser síncrono (esperamos a la operación de escritura) o asíncrono (no esperamos a la operación de escritura). Básicamente son &lt;em&gt;colas&lt;/em&gt; donde metemos las queries y los commands para que se ejecuten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Veamos gráficamente como quedaría el ejemplo anterior (fíjate en que cada color que representa la capa a la que pertenece):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m3voaYJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aeq6jMtIj43CvRSVKkxrGUg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m3voaYJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aeq6jMtIj43CvRSVKkxrGUg.png" alt="" width="800" height="305"&gt;&lt;/a&gt;Ahora el controlador “encola” el comando en un bus que puede ser síncrono o asíncrono, y esta petición es resuelta por el manejador (handler) asociado&lt;/p&gt;

&lt;p&gt;Este bus de asíncrono será la base de lo que más adelante veremos como &lt;em&gt;comunicación basada en eventos.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Detalles de diseño a nivel macroarquitectura
&lt;/h3&gt;

&lt;p&gt;Ahora que tenemos claro como desarrollar nuestros microservicios nos enfrentamos al reto de hacer que hablen entre ellos, que se comuniquen.&lt;/p&gt;

&lt;p&gt;Cuando teníamos un monolito esto no implicaba mayor problema, ya que todo quedaba en casa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3BYV15Mv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A_Bl6std4tuk13NVRvUHpdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3BYV15Mv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A_Bl6std4tuk13NVRvUHpdg.png" alt="" width="800" height="716"&gt;&lt;/a&gt;Esquema de arquitectura monolítica&lt;/p&gt;

&lt;p&gt;Todas las peticiones apuntan al mismo sitio, solo hay una conexión a una base de datos y esa base de datos es la única fuente de datos de toda la plataforma.&lt;/p&gt;

&lt;p&gt;Como ya hemos comentado antes, en el caso de que, por ejemplo, la creación de posts se incrementara de forma inesperada, la única base de datos del nuestro sitio se saturaría por las escrituras que está recibiendo por parte de usuarios publicando contenido. Esto por supuesto afectaría al endpoint de obtener usuarios, aumentando los tiempos de respuestas e incluso obteniendo timeouts.&lt;/p&gt;

&lt;p&gt;En el caso de tener microservicios la comunicación es más compleja, pero podemos evitar el problema de que un pico de peticiones de un tipo en concreto nos tumbe el sitio entero.&lt;/p&gt;

&lt;p&gt;Vamos a ver a continuación distintas formas de comunicación en microservicios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Formas de comunicación
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Microlitos sin infraestructura
&lt;/h4&gt;

&lt;p&gt;Un caso muy común cuando se empieza con a migrar una arquitectura monolítica a una basada en microservicios es &lt;em&gt;romper&lt;/em&gt; el monolito en otros más pequeños que popularmente reciben el nombre de &lt;em&gt;microlitos&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;El esquema que vamos a ver a continuación sería el de &lt;em&gt;Microlitos sin infraestructura:&lt;/em&gt; aunque hemos separado a nivel software el código en distintos servicios, seguimos compartiendo la infraestructura común (en este caso la base de datos).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hjD6KocG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANJCZ14G_ZiHV6jX1WhAKdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hjD6KocG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ANJCZ14G_ZiHV6jX1WhAKdg.png" alt="" width="800" height="383"&gt;&lt;/a&gt;Microlitos sin infraestructura&lt;/p&gt;

&lt;p&gt;¿Se puede considerar este esquema como una arquitectura de microservicios? A duras penas podemos decir que cumple con todas las condiciones para ser un esquema de microservicios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Cada servicio gestiona una parte de negocio única y exclusivamente.&lt;/li&gt;
&lt;li&gt;❌ No puede desplegarse y escalarse de forma independiente sin tener esto efecto sobre el resto de servicios. Si por ejemplo desplegamos una nueva versión del microservicio de usuarios que aplica cambios a la base de datos, puede afectar al microservicio de posts.&lt;/li&gt;
&lt;li&gt;❌ No son independientes, una sobrecarga de peticiones en el microservicio de posts seguiría perjudicando al microservicio de usuarios.&lt;/li&gt;
&lt;li&gt;❌ No utilizan mecanismos de comunicación de baja latencia para comunicarse, de hecho, no se comunican, la base de datos es el único intermediario, toda la información obtenido por cada microservicio sale del mismo sitio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es un punto de partida, pero no podemos quedarnos aquí indefinidamente, debemos evolucionar nuestra arquitectura.&lt;/p&gt;

&lt;h4&gt;
  
  
  Microlitos vía HTTP
&lt;/h4&gt;

&lt;p&gt;Una segunda parada en el camino hacia los microservicios independientes es hacer que nuestros microlitos es dejar de compartir la base de datos.&lt;/p&gt;

&lt;p&gt;Puesto que el microlito de usuarios solo mantiene datos relacionados con los usuarios, es posible que surja la necesidad de obtener alguna información relacionada con los posts propiedad de ese usuario, por ejemplo, saber el número de posts que ha publicado.&lt;/p&gt;

&lt;p&gt;No podemos guardar ese dato, no nos corresponde. Cada microlito expone una API por lo que parece una buena opción que nuestros microlitos se comuniquen vía HTTP para obtener la información necesaria.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gTKZVAnA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjeKV_mQh8AQU8CWp5daO_A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gTKZVAnA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AjeKV_mQh8AQU8CWp5daO_A.png" alt="" width="800" height="471"&gt;&lt;/a&gt;El color azul del campo “total_posts” denota que es un dato que proviene de la base de datos de posts.&lt;/p&gt;

&lt;p&gt;Ahora que nuestros microlitos tienen cada uno su propia base de datos no nos preocupa que una sobrecarga en el número de peticiones de crear posts bloqueen el microlito de usuarios… &lt;strong&gt;o sí debería preocuparnos?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aunque somos independientes a nivel código e infraestructura, una eventual caída de otro microlito podría dejarnos fuera de juego también, ya que si el número de peticiones POST aumenta en el microlito de posts, esto afectará también a las peticiones GET que hacemos desde el microlito de usuarios, la base de datos puede seguir bloqueándose y por tanto bloquearnos.&lt;/p&gt;

&lt;p&gt;Y cómo solucionamos esto? Circuit Breaker al rescate!&lt;/p&gt;

&lt;h4&gt;
  
  
  Circuit Breaker
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://martinfowler.com/bliki/CircuitBreaker.html"&gt;Circuit Breaker&lt;/a&gt; es un patrón popularizado por Michael T. Nygard en el libro &lt;a href="https://amzn.to/3fccteZ"&gt;&lt;em&gt;Release It!&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; básicamente se basa en el comportamiento que tiene un fusible en un circuito eléctrico: cuando algo se sobrecarga actúa como barrera abriendo el circuito (en electrónica un circuito eléctrico es aquel que esta discontinuado, y por lo tanto no funciona). Cómo se aplicaría esto a microservicios? Miremos el siguiente esquema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LaWpVhBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2APoLtdjj4fI2IDLgEPambXA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LaWpVhBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2APoLtdjj4fI2IDLgEPambXA.png" alt="" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el la línea de eventos podemos ver como el cliente solicita a un servicio un dato, pero este tiene un intermediario, el circuit breaker. Este circuit breaker esta configurado para tener un umbral de error de 2 reintentos, al segundo fallo &lt;em&gt;abrirá&lt;/em&gt; el circuito y dejará de haber comunicación entre cliente y servicio.&lt;/p&gt;

&lt;p&gt;Tal y como muestra el gráfico, tras dos errores, la comunicación es cortada y aquí podemos optar por técnicas como mostrar un valor por defecto para el dato consultado (por ejemplo, en este caso, total_posts: 0 sería una solución de compromiso).&lt;/p&gt;

&lt;p&gt;Esta apertura del circuito permite al servicio recuperarse de la avalancha de tráfico que le ha hecho caer. Obviamente pasado un tiempo el circuito vuelve a cerrarse y vuelve a aceptar peticiones, pero no voy a entrar en detalle en cómo se hace esto.&lt;/p&gt;

&lt;p&gt;Otro dato importante, aunque en el esquema solo se vea un servicio, en una arquitectura de microservicios cloud lo habitual es tener más de un servicio detrás del circuit breaker:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dXTBIzO5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AkvOtCK0AzEQp6qQ5F5BcdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dXTBIzO5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AkvOtCK0AzEQp6qQ5F5BcdA.png" alt="" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Eventos de dominio
&lt;/h4&gt;

&lt;p&gt;La última forma de comunicación que vamos a ver es a través de eventos de dominio, una forma que desde mi punto de vista tiene una serie de ventajas respecto a escalabilidad bastante interesante.&lt;/p&gt;

&lt;p&gt;Partimos del concepto de “dominio” que ya hemos comentado antes cuando hablábamos de arquitectura hexagonal a nivel de diseño de microarquitectura. Como su nombre indica, un evento de dominio representa un suceso que ha ocurrido en nuestro sistema, relacionado con el dominio de nuestra aplicación, nuestro &lt;em&gt;core&lt;/em&gt;, nuestra lógica de negocio.&lt;/p&gt;

&lt;p&gt;Algunas características de los eventos de dominio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deben de ser serializables en un formato que permita interoperabilidad.&lt;/strong&gt; Recordemos que nuestros microservicios son tecnológicamente independientes, si emitimos un evento serializado con el formato nativo de nuestro lenguaje (PHP, JAVA, Python…) difícilmente va a ser entendible para otros microservicios que usen un stack diferente. Formatos como JSON, XML o YAML son ejemplos de formatos que permiten la interoperabilidad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deben de ser identificables.&lt;/strong&gt; Cada evento debe de ser capaz de ser buscado por un identificador único, con lo que debemos asegurarnos de utilizar un sistema de identificación que no lleve a error. Formatos autonuméricos incrementales suelen ser una mala idea: vamos a tener muchos microservicios emitiendo eventos, ¿cómo llevamos la cuenta del autoincremento? Sistemas como los UUID dan garantías de unicidad y también son un formato de identificación interoperable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La fecha es importante.&lt;/strong&gt; Tan importante como su identificación es saber &lt;strong&gt;cuándo&lt;/strong&gt; sucedió. En el caso de eventos es importante poder ordenarlos de forma unívoca (recordemos que no podemos usar identificadores autonuméricos), por lo que la fecha es muy importante. Ahora bien, tenemos que tener en cuenta que el formato de fecha y hora debe de ser interoperable entre distintos stack, por lo que es importante usar formatos como &lt;a href="https://es.wikipedia.org/wiki/ISO_8601"&gt;ISO-8601&lt;/a&gt; o &lt;a href="https://es.wikipedia.org/wiki/Tiempo_Unix"&gt;POSIX Timestamp&lt;/a&gt;. Algo de vital importancia también es usar como zona horaria UTC, ya que podemos tener microservicios operando en distintas zonas horarias y eso puede causar un caos informativo. A través de UTC podemos transformar la fecha a cualquier franja horaria sin mayores complicaciones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Han ocurrido ya (pasado).&lt;/strong&gt; Esto es importante tenerlo en cuenta a la hora de definir una estrategia de nombrado para nuestros eventos de dominio, esto es importante para poder distinguir un evento de dominio (verbos en pasado) de acciones o casos de uso (verbos en infinitivo).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formato estandarizado.&lt;/strong&gt; Además del nombre del evento, también el contenido del evento debe de seguir una estandarización. En el cuerpo de un evento debemos de encontrar la información necesaria para manejar la situación, ya que la respuesta habitual a un evento son los efectos secundarios o &lt;em&gt;side-effects&lt;/em&gt;, una respuesta del sistema ante tal evento. Que todos los eventos tengan una estructura similar simplifica el desarrollo de &lt;em&gt;listeners&lt;/em&gt; para nuestros eventos de dominio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No necesariamente todo evento debe de disparar efectos secundarios.&lt;/strong&gt; No solo debemos de lanzar eventos cuando deseemos que ocurra un efecto secundario, en una arquitectura orientada a eventos todo suceso debe de quedar registrado, aunque no haya ningún efecto secundario esperando a que suceda un evento. Esto además nos permite llevar un registro (da igual la forma: base de datos, archivos de log…) de todo cuanto sucede en nuestro sistema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algunos ejemplos de serializado de un evento de dominio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A-uh5cbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/734/1%2A1gM06vJS0YOmfg9cSjilrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A-uh5cbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/734/1%2A1gM06vJS0YOmfg9cSjilrg.png" alt="" width="734" height="553"&gt;&lt;/a&gt;Contenido basado en primitivas&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JyndABEl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/732/1%2AIx5rBgC5hS2JI8WsUj-h1A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JyndABEl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/732/1%2AIx5rBgC5hS2JI8WsUj-h1A.png" alt="" width="732" height="680"&gt;&lt;/a&gt;Contenido basado en objetos&lt;/p&gt;

&lt;p&gt;Como se puede apreciar en ambos ejemplos, la información relativa al evento se puede expresar de múltiples maneras, lo importante es conservar un esqueleto común a todos los eventos y que el contenido propio de cada evento se adapte a las necesidades de cada caso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3qcwUeEP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/609/1%2A9zkAuDGP_3gDNwu7hDwJsQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3qcwUeEP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/609/1%2A9zkAuDGP_3gDNwu7hDwJsQ.png" alt="" width="609" height="338"&gt;&lt;/a&gt;Esqueleto común&lt;/p&gt;

&lt;p&gt;Me gustaría dar una opinión personal al respecto del contenido de los eventos, y es que es mejor añadir información de más que de menos. Hay que intentar adelantarse en la medida de lo posible a las futuras necesidades de los manejadores de eventos, ya que es probable que si actualizamos en algún momento el cuerpo de nuestros eventos, en el momento de hacer el despliegue haya todavía en cola muchos eventos con el anterior contenido, y eso puede darnos pie a errores en el manejo de los eventos.&lt;/p&gt;

&lt;h4&gt;
  
  
  Comunicación mediante eventos de dominio
&lt;/h4&gt;

&lt;p&gt;Ahora que estamos ya familiarizados con el concepto de eventos de dominio, vamos a ver cómo quedaría nuestra macroarquitectura de comunicación en el siguiente gráfico:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m8BWlZXt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AeZ1ajhe-tPo8vMWlVAeebQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m8BWlZXt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AeZ1ajhe-tPo8vMWlVAeebQ.png" alt="" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hemos incorporado un nuevo elemento a nuestra arquitectura de comunicación: el &lt;em&gt;bus de eventos.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Los microservicios ya no se comunican directamente entre ellos, sino que lo hacen a través de un nuevo elemento arquitectural que implementa el &lt;em&gt;patrón Pub/Sub (Publisher/Subscriber).&lt;/em&gt; No hemos hablado nunca en el blog sobre este patrón así que vamos a dar unas pinceladas sobre cómo funciona para meternos en contexto.&lt;/p&gt;

&lt;h4&gt;
  
  
  Patrón Pub/Sub
&lt;/h4&gt;

&lt;p&gt;El patrón Pub/Sub ofrece una forma eficaz de comunicación asíncrona desacoplando a los emisores de mensajes de sus receptores, evitando de esta manera que el emisor quede bloqueado a la espera de una respuesta.&lt;/p&gt;

&lt;p&gt;Hay 3 actores principales en este patrón:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Emisor (Publisher):&lt;/strong&gt; Es quien &lt;em&gt;lanza&lt;/em&gt; un evento, quien decide comunicar que algo ha sucedido, permitiendo a quien esté interesado en reaccionar de alguna manera hacerlo, pero sin depender de la respuesta de estos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bus de Eventos (Message Broker):&lt;/strong&gt; Es el canal de comunicación donde el emisor publica sus mensajes (eventos) y es este mismo sistema el encargado de notificar a los suscriptores de que se ha producido el evento que están interesados en manejar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriptor (Subscriber):&lt;/strong&gt; Es el &lt;em&gt;cliente&lt;/em&gt;, el receptor de el mensaje. No necesariamente debe de haber un único subscriptor para cada mensaje, ni un mismos subscriptor debe de estar esperando un único tipo de mensajes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para garantizar la asincronía el bus de eventos suele delegar su capa de transporte sobre un servicio de colas de mensajería como puede ser Redis, RabbitMQ, Apache Kafka, IronMQ, AmazonSQS, MQTT… que disponen de muchas funcionalidades extra que permiten manejar de forma optima todos los puntos oscuros de este patrón, como los eventos desordenados o los duplicados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Añade una capa de indirección entre productor de mensajes y consumidores. Esto incluso nos permite tener productores implementados en un lenguaje diferente al que ha sido implementado el consumidor (y viceversa). Este desacople es una de las virtudes por las que la arquitectura de microservicios es elegida.&lt;/li&gt;
&lt;li&gt;Se evitan bloqueos a la hora de esperar una respuesta por parte del consumidor. Si es necesaria una respuesta, la recibiremos por el mismo Bus en el que hemos publicado nosotros el mensaje, y podremos subscribirnos a ella, mientras tanto, podemos seguir con nuestro trabajo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Inconvenientes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Añade una capa de indirección entre productor de mensajes y consumidores. La misma virtud puede llegar a ser un defecto en determinados escenarios. Tenemos que estar seguros de no necesitar una respuesta inmediata a nuestro evento. El debug en estos casos también se vuelve mucho más complejo.&lt;/li&gt;
&lt;li&gt;Las colas pueden saturarse y esto puede acabar con efectos secundarios poco deseados, como mensajes duplicados o mensajes que llegan desordenados. Mas adelante profundizaremos en esto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por lo tanto, la comunicación de nuestros microservicios ahora queda delegada a un nuevo elemento con gran capacidad de escalado, por lo que no podemos llegar a saturarlos por llamadas internas entre ellos como en el caso de comunicación por HTTP.&lt;/p&gt;

&lt;h4&gt;
  
  
  Consistencia Eventual
&lt;/h4&gt;

&lt;p&gt;Antes hemos introducido el concepto de &lt;em&gt;consistencia eventual&lt;/em&gt; sin entrar en mucho detalle, para hacernos una idea y sin entrar en mucho detalle, podríamos definir la consistencia eventual como &lt;strong&gt;el hecho de que la información en todos nuestros microservicios puede no estar perfectamente actualizada en todo momento (no es consistente), pero que tarde o temprano acabará estándolo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Por qué sucede esto? Es fácil suponer que en un sistema formado por eventos que fuerza la actualización de los datos en distintos microservicios, todo esto no ocurre de forma simultánea ni cohesionada, cada microservicios puede tener sus tiempos, su carga de trabajo, su latencia, sus tiempos de ejecución…&lt;/p&gt;

&lt;p&gt;Estamos en un ecosistema muy diverso a muchos niveles: podemos tener múltiples stacks tecnológicos a nivel de microarquitectura, con lenguajes más o menos rápidos, con distintas cargas de trabajo, probablemente con sistemas de bases de datos diferentes que puede que estén optimizadas para lectura y no para escritura o al revés… Así que tenemos que convivir con el hecho de que no todo estará siempre actualizado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo evitar la consistencia eventual?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ni puedo ni me atrevo a profundizar en este post sobre este tema, ya que daría para una nueva colección de posts, pero sí, existen formas de &lt;em&gt;convivir&lt;/em&gt; con la consistencia eventual, por ejemplo con las &lt;a href="https://en.wikipedia.org/wiki/Distributed_transaction"&gt;&lt;strong&gt;transacciones distribuidas&lt;/strong&gt;&lt;/a&gt; aunque también tengan sus &lt;a href="https://www.grahamlea.com/2016/08/distributed-transactions-microservices-icebergs/"&gt;&lt;strong&gt;puntos oscuros&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hay otras corrientes de pensamiento que afirman que si necesitas que varios sistemas sean siempre consistentes, quizá deberían ser un único sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sistemas de colas
&lt;/h3&gt;

&lt;p&gt;El uso de sistemas de colas como RabbitMQ, MQTT, Amazon SQS… y otros proveedores es uno de los puntos fuertes de la comunicación basada en eventos de dominio.&lt;/p&gt;

&lt;p&gt;Estos sistemas también llamados brokers de mensajería nos permiten comunicar nuestros eventos en una amplia variedad de formas, por mi parte puedo hablar más específicamente de RabbitMQ que es el que más he usado y que me parece muy potente y versátil.&lt;/p&gt;

&lt;p&gt;En todo sistema de colas tenemos una serie de actores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Productores:&lt;/strong&gt; Son quienes &lt;em&gt;emiten&lt;/em&gt; el mensaje&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exchange/Broker:&lt;/strong&gt; Es el sistema encargado de distribuir el mensaje en las colas apropiadas, pueden tener distintas formas de distribución: &lt;em&gt;topic, fanout&lt;/em&gt; o &lt;em&gt;direct.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colas:&lt;/strong&gt; Son los &lt;em&gt;recipientes&lt;/em&gt; de los mensajes, a las colas se conectan los consumidores para obtener los mensajes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumidores:&lt;/strong&gt; Son quienes se conectan a las colas en busca de mensajes que procesar. Si procesan el mensaje de forma correcta devuelven a la cola un código ACK indicando que el procesamiento ha sido correcto, en caso contrario, responderán a la cola con un NACK, provocando que el mensaje sea reencolado para volver a ser consumido posteriormente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como antes decía, el broker puede estar configurado para distribuir los mensajes de varias maneras, veamos en el caso de RabbitMQ como funcionan estas tres formas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fanout:&lt;/strong&gt; Los mensajes recibidos se envían a todas las colas sin excepción.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6xEQisNA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2A4bdLiV_pOLbe8nvsYN0NeQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6xEQisNA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2A4bdLiV_pOLbe8nvsYN0NeQ.gif" alt="" width="800" height="507"&gt;&lt;/a&gt;Exchange en modo fanout, el mensaje llega a todas las colas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Direct:&lt;/strong&gt; El mensaje se publica solo a las colas suscritas a ese tipo de mensaje. El &lt;em&gt;tipo&lt;/em&gt; suele ser el nombre del evento producido.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sbn379Vh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2A9x_t5SE4cgrRMaTjjzOQkQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sbn379Vh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2A9x_t5SE4cgrRMaTjjzOQkQ.gif" alt="" width="800" height="507"&gt;&lt;/a&gt;Exchange en modo direct, solo aquellas colas cuya binding key coincida con el mensaje lo van a poder recibir.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Topic:&lt;/strong&gt; Es como &lt;strong&gt;direct&lt;/strong&gt; , solo que permite el uso de expresiones regulares, por ejemplo, en &lt;strong&gt;direct&lt;/strong&gt; la clave o &lt;em&gt;binding key&lt;/em&gt; de una cola podría ser post.created_,_ en &lt;strong&gt;topic&lt;/strong&gt; la binding key podría ser post.* y estaría suscrito a cualquier mensaje que empiece por &lt;em&gt;post.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3COAN1uv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2AQPfiZwzRXmHcQgfZwStAKg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3COAN1uv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/800/1%2AQPfiZwzRXmHcQgfZwStAKg.gif" alt="" width="800" height="507"&gt;&lt;/a&gt;Exchange en modo topic. Si el nombre del tipo de mensaje pasa por la regex de la binding key, la cola recibe el mensaje.&lt;/p&gt;

&lt;p&gt;Todos estos modos de operar de las colas nos permiten una amplia flexibilidad, podemos usar por ejemplo el modo topic y crear una cola suscrita a los eventos de tipo *.log y añadir un consumidor que se encarga de hacer un logging de todos los eventos producidos.&lt;/p&gt;

&lt;p&gt;Otras ventajas de estos sistemas es su fácil escalabilidad, al tratarse de servicios de infraestructura (como las bases de datos o las cachés), podemos tener tantas instancias como necesite nuestro sistema y crecer de forma indefinida.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gestión de errores de las colas
&lt;/h3&gt;

&lt;p&gt;Básicamente hay dos errores que se pueden producir al usar eventos de dominio con sistemas de colas, y son los eventos desordenados, y nada lo ejemplifica mejor que este twitt de Mathias Verraes:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-632260618599403520-835" src="https://platform.twitter.com/embed/Tweet.html?id=632260618599403520"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-632260618599403520-835');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=632260618599403520&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Algo que podríamos traducir como:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hay dos problemas difíciles en sistemas distribuidos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recibir el evento sólo una vez
&lt;/li&gt;
&lt;li&gt;El orden de los eventos
&lt;/li&gt;
&lt;li&gt;Recibir el evento sólo una vez&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Eventos desordenados y Dead letter queues
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hm5U5uHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/552/1%2ApXhbvytvsswfWJVl_8h-Tg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hm5U5uHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/552/1%2ApXhbvytvsswfWJVl_8h-Tg.jpeg" alt="" width="552" height="368"&gt;&lt;/a&gt;En ocasiones el orden es importante.&lt;/p&gt;

&lt;p&gt;Hay sistemas de colas que no garantizan el orden de entrega, de hecho, es casi lo más habitual.&lt;/p&gt;

&lt;p&gt;Esto puede no ser un problema por sí mismo, salvo que los eventos desordenados sean dependientes entre sí, por ejemplo notificar a un usuario de que su autor favorito ha escrito un nuevo post antes de el evento de que el post ha sido creado haya sido recibido. Esto podría provocar un error de consistencia eventual al tratar de buscar el post si aún no existe en la base de datos.&lt;/p&gt;

&lt;p&gt;Una forma de gestionar estos errores es el uso de &lt;a href="https://en.wikipedia.org/wiki/Dead_letter_queue"&gt;&lt;em&gt;dead-lettering&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt; Esto básicamente consiste en llevar una cuenta de las veces que un mensaje ha sido devuelto con un NACK, si supera cierto umbral, este mensaje es mandado a una cola de dead-lettering, donde un consumidor especial podrá procesarlo de la manera adecuada:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elimándolo&lt;/li&gt;
&lt;li&gt;Notificando a alguien del suceso&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Eventos duplicados
&lt;/h4&gt;

&lt;p&gt;Cuando nuestra infraestructura de colas crece y aumentan el número de máquinas que la controlan, existe la posibilidad de que un mismo evento se envíe dos veces o más (por distintas máquinas). Los sistemas de colas distribuidas necesitan mantener los mensajes en un espacio compartido, que bien puede ser memoria o disco duro. En ambos casos se produce una latencia que puede provocar el envío de un mensaje de forma duplicada:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;La máquina A envía el mensaje 815c5068-72e6-40ad-96f1-b0ec7cd57d73&lt;/li&gt;
&lt;li&gt;El consumidor A empieza el procesado del mensaje 815c5068-72e6-40ad-96f1-b0ec7cd57d73&lt;/li&gt;
&lt;li&gt;La máquina B envía el mensaje 815c5068-72e6-40ad-96f1-b0ec7cd57d73&lt;/li&gt;
&lt;li&gt;El consumidor A envía un ACK a la máquina A&lt;/li&gt;
&lt;li&gt;El consumidor B empieza el procesado del mensaje 815c5068-72e6-40ad-96f1-b0ec7cd57d73&lt;/li&gt;
&lt;li&gt;La máquina A elimina el mensaje 815c5068-72e6-40ad-96f1-b0ec7cd57d73&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Entre el paso 1 y 6 el mensaje sigue disponible para ser enviado a consumidores, por lo que si el procesado es largo puede provocar que se procese más de una vez.&lt;/p&gt;

&lt;p&gt;En realidad los sistemas de colas disponen de mecanismos para evitar estos problemas (sistemas de &lt;em&gt;lock&lt;/em&gt; que impiden que se sirva dos veces el mismo mensaje), pero tienen un alto coste en el rendimiento de las colas y suele preferirse prescindir de él y manejar los posibles errores de duplicidades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo gestionamos estos errores?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;De nuevo muy a &lt;em&gt;grosso modo&lt;/em&gt; vamos a ver unas posibles soluciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dead Lettering.&lt;/strong&gt; Si el mensaje no puede ser procesado dos veces, dará un error y el consumidor devolverá un NACK, si esto se produce las veces suficientes, acabará en Dead Lettering y será procesado de otra manera.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registro de mensajes ejecutados.&lt;/strong&gt; Podemos llevar un registro con el id de todos los mensajes ejecutados, y antes de ejecutar un nuevo mensaje, comprobar si ya ha sido previamente ejecutado. Esto en un entorno de muchos consumidores para un mismo mensaje, puede seguir dando problemas, ya que mientras se registra el mensaje como procesado podría volverse a procesar.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://es.wikipedia.org/wiki/Idempotencia"&gt;&lt;strong&gt;Idempotencia&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;.&lt;/strong&gt; Este concepto nos garantiza que la misma ejecución de un evento repetidas veces producirá el mismo resultado. Por ejemplo, en el caso de un evento de post.created intentaremos volver a insertar ese registro en nuestra base de datos, si obtenemos un error porque el registro ya existe, simplemente ignoraremos el error y devolveremos un ACK a la cola. Otra opción sería antes de intentar insertar el registro comprobar si existe previamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusiones&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Las arquitecturas de microservicios son complejas, pero resuelven muchos problemas de escalabilidad y crecimiento allá donde es necesario.&lt;/p&gt;

&lt;p&gt;Probablemente si no trabajamos en grandes empresas con tráfico masivo y picos que puedan hacer peligrar la disponibilidad del servicio, jamás nos veremos ante un proyecto que requiera de su uso.&lt;/p&gt;

&lt;p&gt;Pero no por ello es una solución innecesariamente complicada o basada en la sobreingeniería, solo lo será si intentamos matar moscas a cañonazos y decidimos implementar esta arquitectura por ser un poco más &lt;em&gt;mainstream&lt;/em&gt; o porque es el concepto de moda.&lt;/p&gt;

&lt;p&gt;Quizá se hable más ahora que hace 20 años de microservicios porque el número de grandes empresas con estas necesidades ha crecido y ha popularizado el termino, pero eso no lo convierte en un martillo de oro.&lt;/p&gt;

&lt;p&gt;Espero que os haya gustado este post, aunque se ha quedado bastante más largo de lo habitual ;)&lt;/p&gt;

&lt;p&gt;Saludos y hasta la próxima!&lt;/p&gt;




</description>
      <category>microservicios</category>
      <category>designpatterns</category>
      <category>cleancode</category>
      <category>php</category>
    </item>
  </channel>
</rss>
