sábado, 11 de enero de 2020

Capítulo 18: Anatomía del límite - Clean Architecture


Cruce de límites
En tiempo de ejecución un cruce de límite no es más que una función en una cara del límite llamando a una función del otro lado pasándole unos datos. El truco para crear un apropiado cruce de límites es administrar las dependencias del código fuente. 

¿Por qué el código fuente? Porque cuando un módulo de código fuente cambia otro módulos pueden tener que cambiar o recompilar y, entonces, redesplegar. Administrar y construir esos cortafuegos contra esos cambios es el propósito de los límites.
El temido monolito
Es el más simple y común de los límites arquitectónicos ya que no tiene una representación física estricta. El monolito es una organización de funciones y datos dentro de un mismo servidor.

El hecho de que el monolito no tenga unos límites físicos no quiere decir que no estén presentes y no tengan significado. La habilidad para desarrollar independientemente los diversos componentes para el ensamblaje final tiene un valor enorme.

El cruce de límite más simple es una llamada desde un cliente de bajo nivel a un servicio de alto nivel. 
En la siguiente figura se puede observar como el flujo de control cruza el límite de izquierda a derecha. El cliente «client» llama a la función «f()» de «Service». Este pasa una una instancia de «Data». El marcador «DS» indica una estructura de datos. Los datos «Data» se pueden pasar como un argumento a la función «f()» o por otro medio un poco más elaborado. Se puede observar que la definición de «Data» se encuentra en el lado del servicio.
Cuando un cliente de alto nivel necesita invocar un servicio de bajo nivel, el polimorfismo dinámico se utiliza para invertir la dependencia contra el flujo de control. La dependencia en tiempo de ejecución se opone a la dependencia en tiempo de compilación.

En la siguiente figura se puede observar que se cruzan los límites de izquierda a derecha, igual que antes. El cliente de alto nivel hace una llamada a la función «f()» de el servicio de bajo de nivel «service impl» a traves de la interfaz «Service».

En este caso se puede apreciar como todas las dependencias cruzan los límites de la derecha a la izquierda hacia el componente de nivel superior. Nótese también que la definición de la estructura de datos está en el lado izquierdo del límite. 

Incluso en un monolito, este tipo de particionado disciplinado puede ser de gran ayuda para el desarrollo, pruebas y despliegue. Los equipos pueden trabajar independientementes unos de otros en sus propios componentes sin pisarse entre ellos.

Los componentes de alto nivel permanecen independientes de los niveles de bajo nivel. 
Despliegue de componentes
El despliegue es simplemente el encuentro de los distintos componentes de alguna forma que se pueden ejecutar. 
Threads
Tanto los monolitos como sistemas más sofisticados pueden usar «threads». Estos no son límites arquitectonicos o unidades de despliegue pero son una manera de organizar la programación y el orden de ejecución. Pueden estar totalmente contenidos dentro de un componente o extenderse a través de muchos componentes.
Procesos locales
De lejos el límite arquitectonico más fuerte es el proceso local. Un proceso local se crea típicamente desde la consola o una llamada local equivalente. Los procesos locales se suelen comunicar por sockets o algún otro tipo de sistema de comunicación como colas de mensajería o mailboxes.

Un proceso local es como una especie de súper componente: el proceso consiste en componentes de nivel inferior que gestionan sus dependencias a través del polimorfismo dinámico.

La estrategia de segregación entre procesos locales es la misma que para los monolitos y componentes binarios. Las dependencias del código fuente apuntan en la misma dirección a través del límite, y siempre hacia el componente de nivel superior.
Para los procesos locales, esto significa que el código fuente de los procesos de nivel superior no debe contener los nombres, las direcciones físicas o las claves de búsqueda del registro de los procesos de nivel inferior. Recuerde que el objetivo arquitectónico es que los procesos de nivel inferior sean complementos de procesos de nivel superior.

La comunicación a través de los límites del proceso local implica llamadas al sistema operativo, cálculo y descodificación de datos e interruptores de contexto entre procesos, que son moderadamente costosos. El chattiness debe ser cuidadosamente limitado.
Servicios
El límite más marcado es un servicio. Un servicio es un proceso, generalmente empezado desde la línea de comandos o a través de una llamada al sistema equivalente. Los servicios no dependen de su localización física. Dos servicios pueden o no operar en el mismo procesador o núcleo múltiple. Los servicios asumen que toda la comunicación toman lugar a través de la red. 

La comunicación entre los límites de los servicios son muy lentas en comparación con las llamadas a funciones. Los tiempos de respuesta pueden variar de decenas de milisegundos a segundos. Se debe evitar chatear cuando sea posible dado que la comunicación a este nivel implica altos niveles de latencia. 

De otra manera, las mismas reglas aplican a servicios como a procesos locales. Los servicios de bajo nivel deberían enchufar a los servicios de alto nivel. El código fuente de los servicios de alto nivel no deben contener ningún conocimiento físico (por ejemplo una URL) de ningún servicio de bajo nivel. 

No hay comentarios:

Publicar un comentario