martes, 7 de enero de 2020

Capítulo 16: Independencia - Parte 1 - Clean Architecture


Como se ha establecido anteriormente una buena arquitectura debe dar soporte a:

  • Los casos de uso y operaciones del sistema.
  • El mantenimiento del sistema.
  • El desarrollo del sistema.
  • El despliegue del sistema.
Los casos de uso
Los casos de uso establecen el comportamiento de un sistema. Si el sistema fuera un carrito de la compra entonces la arquitectura debe dar soporte a los casos de uso del carrito de compra. En realidad, esta es la principal preocupación del arquitecto y la principal prioridad de la arquitectura.

No obstante, la arquitectura no ejerce influencia alguna sobre el comportamiento del sistema. Hay muy pocas opciones de comportamiento que el arquitecto puede dejar abiertas. La función más importante que puede llevar a cabo la arquitectura para apoyar el comportamiento es clarificar y exponer ese comportamiento de manera que la intención del sistema es visible en el ámbito de la arquitectura.
Por ejemplo, una sistema que sea un carrito de compra con una buena arquitectura parecerá un sistema de carrito de compra. Los casos de uso de ese sistema estarán plenamente visibles dentro de la estructura del sistema. Los desarrolladores no tendrán que buscar estos comportamientos dado que esos comportamientos serán comportamientos de primera clase visibles en el nivel superior del sistema. Esos elementos serán clases, funciones o módulos que ocupan posiciones prominentes dentro de la arquitectura los cuales tendrán nombres que describan claramente su función.
Operación
La arquitectura juega un papel sustancial en el soporte del funcionamiento del sistema así como en su rendimiento. Por ejemplo, si un sistema debe soportar 10.000 compradores por segundo la arquitectura debe aportar una estructura de los diversos componentes de manera que permita llegar a ese rendimiento.

Si un sistema comienza su desarrollo con un monolito y la arquitectura que utiliza no es la adecuada, el acoplamiento y la comunicación entre los distintos componentes no va a permitir una evolución sencilla a otras soluciones como pudieran ser los microservicios. No obstante, si la arquitectura mantiene el aislamiento adecuado entre los componentes y no asume los medios de comunicación entre esos componentes será mucho más fácil evolucionar a medida que las necesidades operativas del sistema cambien con el tiempo.
Desarrollo
La arquitectura juega un papel importante en el apoyo al entorno de desarrollo. Aquí es donde entra en juego la ley de Conway. La ley de Conway dice:

“Cualquier organización que diseñe un sistema producirá un diseño cuya estructura sea una copia de la estructura de comunicación de la organización.”
.
Cuando una organización tiene que desarrollar un sistema con muchos equipos y preocupaciones debe tener una arqutiectura que facilite las acciones independientes de esos equipos de manera que estos no interfieran entre sí durante el desarrollo. Esto se consigue mediante la partición correcta del sistema en componentes aislados. Estos componentes se pueden asignar a distintos equipos de manera que puedan trabajar de forma independiente.
Despliegue
La arquitectura también juega un papel importante a la hora de desplegar un sistema. El objetivo es un despliegue inmediato. Con una buena arquitectura, el despliegue no se basa en docenas de pequeños scripts de configuración y ajustes de archivos de propiedades. 

Esto se logra a través de la partición y asilamiento adecuado de los componentes del sistema, incluidos los componentes maestros que unen todo el sistema y aseguran que cada componente se inicie, integre y supervise adecuadamente.
Dejando las opciones abiertas
Una buena arquitectura equilibra todas estas preocupaciones con una estructura de componentes que satisface las distintas necesidades.

La realidad es que lograr este equilibrio es bastante difícil. El problema es que la mayoría de las veces las especificaciones no están completas, ni la estructura del equipo y lo peor es que los requisitos van cambiando con el tiempo a medida que el sistema se desarrolla. Así que, en resumen, los objetivos que debemos cumplir son confusos e inconstantes. Fantástico.

Afortunadamente algunos de los principios de una buena arquitectura son relativamente baratos de implementar y pueden ayudar a equilibrar esas preocupaciones incluso cuando los objetivos son confusos e inconstantes. Estos principios nos ayudan a dividir nuestros sistemas en componentes bien aislados que nos permiten dejar tantas opciones abiertas como sea posible, durante el mayor tiempo posible.

Una buena arquitectura hace que el sistema sea  fácil de cambiar, en todas las formas en que debe cambiar, al dejar las opciones abiertas.
Desacoplando capas
Si consideramos los casos de uso, el arquitecto desea que la estructura del sistema sea compatible con todos los casos de uso necesarios a pesar de no saber cuales son esos casos de uso. No obstante, el arquitecto sabe la intención del sistema. El sistema podría ser un carrito de compras, un sistema de procesamiento de pedidos, etc.

El arquitecto puede emplear el «Principio de responsabilidad única» y el «Principio de cierre común» para separar aquellas cosas que cambian por diferentes razones dado el contexto de la intención del sistema.

¿Qué cosas pueden cambiar por diferentes motivos? Pues hay algunas más obvias que otras. Por ejemplo, las interfaces de usuario pueden cambiar por razones que no tienen nada que ver con las reglas de negocio. Los casos de uso cambian con las reglas de negocio. Un buen arquitecto querrá separar las partes de UI de un caso de uso de las partes de la regla de neocios de tal manera que se puedan cambiar unas de otras independientemente mientras se mantienen esos casos de uso claros y visibles.

Las reglas de negocio pueden ser muy específicas o pueden ser más generales. Por ejemplo, la validación de los campos de entrada es una regla de negocio es una regla más general en contraste con el cálculo del interés de una cuenta de un cliente en un banco lo cuál es una regla más específica del negocio. Estos dos tipos de reglas cambiarán a ritmos diferentes y por diferentes razones por lo que deben separarse para que puedan cambiar  de manera independiente.

La tipo de base de datos, el lenguaje de consulta e incluso el esquema son detalles técnicos que no tienen nada que ver con las reglas de negocio o la interfaz de usuario. Cambiarán a ritmos y por razones diferentes a otros aspectos del sistema. En consecuencia, la arquitectura debe separar el resto del sistema para que puedan cambiarse de forma independiente.

Por lo tanto, encontramos el sistema dividido en capas horizontales desacopladas: la interfaz de usuario, a reglas de negocio específicas de la aplicación, las reglas de negocio independientes de la aplicación y la base de datos, sólo por mencionar algunas.
Desacoplando casos de uso
¿Qué más cambia por diferentes razones? Pues, ¡los casos de uso en sí mismos! Por ejemplo, el caso de uso para agregar un pedido tendrá un ritmo y motivos diferentes de cambio que el caso de uso que elimina un pedido del sistema. Por esta razón, los casos de uso son una forma natural de dividir el sistema.

Los casos de uso son “estrechos cortes verticales” que cortan las capas horizontales del sistema. Cada caso de uso utiliza alguna UI, algunas reglas de negocio específicas de la aplicación, algunas reglas de negocio independientes de la aplicación y algunas funciones de la base de datos. 

Para lograr este desacoplamiento, separamos la interfaz de del caso de uso de agregar un pedido de la interfaz del caso de uso de eliminar un pedido del sistema. Hacemos lo mismo con las reglas de negocio y con la base de datos. Mantenemos los casos de uso separados por la altura vertical del sistema.

Si desacoplamos los elementos del sistema que cambian por diferentes motivos, entonces se puede continuar agregando nuevos casos de uso independientes de los antiguos. Si también se agrupa la UI y la base de datos para admitir esos casos de uso, de modo que cada caso de uso use un aspecto diferente de la UI y la base de datos, entonces es poco probable que la adición de nuevos casos de uso afecte a los más antiguos.
Modo desacoplamiento
 Si los diferentes aspectos de los casos de uso están separados, es probable que los que deben ejecutarse con un alto rendimiento ya estén separados de los que deben ejecutarse con un bajo rendimiento.

Si la interfaz de usuario y la base de datos se han separado de las reglas de negocios, pueden ejecutarse en servidores diferentes. Aquellos que requieren un mayor ancho de banda se pueden replicar en muchos servidores.

En resumen, el desacoplamiento que hicimos por el bien de los casos de uso también ayuda con las operaciones. Sin embargo, para aprovechar el beneficio operativo, el desacoplamiento debe tener el modo apropiado. Para ejecutarse en servidores separados, los componentes separados no pueden depender de estar juntos en el mismo espacio de direcciones de un procesador. Deben ser servicios independientes, que se comunican a través de una red de algún tipo.

Muchos arquitectos llaman a estos componentes "servicios" o "microservicios".. De hecho, una arquitectura basada en servicios a menudo se denomina arquitectura orientada a servicios.

Si esta nomenclatura hace saltar las alarmas en tu mente, tranquilo, no hay de qué preocuparse. Una arquitectura SOA no es la mejor arquitectura posible o que los microservicios son la ola del futuro. Lo que se señala aquí es que en ocasiones tenemos que separar nuestros componentes hasta el nivel de servicio.

Recuerda, una buena arquitectura deja abiertas las opciones. El modo de desacoplamiento es una de esas opciones.

No hay comentarios:

Publicar un comentario