Friday, August 23, 2024

Gestión de gobierno de datos

Session 4: 3h27m

Gestión descentralizada de datos

Cada microservicio tiene sus propios datos, por lo que la integridad y la coherencia de los datos deben considerarse con mucho cuidado.

El principio fundamental de la gestión de datos de microservicios es que cada microservicio debe administrar sus propios datos, podemos llamar a este principio como una base de datos por servicio. Eso significa que los microservicios no deben compartir bases de datos entre sí. En lugar de eso, cada servicio debe ser responsable de su propia base de datos, a la que otros servicios no pueden acceder directamente.

Debe compartir datos a través de los microservicios de la aplicación con el uso de API REST.

La razón de este aislamiento es romper las dependencias innecesarias entre microservicios. Si hay una actualización en el esqumea de base de datos de un microservicio, la actualización no debe afectar directamente a otros microservicios, incluso otros microservicios no deben conocer los cambios en la base de datos. Al aislar las bases de datos de cada sevicio, podemos limitar el ámbito de los cambios en los microservicios cuando se producen cambios en el esquema de la base de datos.

También de esta manera, podemos elegir diferentes bases de datos según los microservicios, qué base de datos puede elegir la mejor opción. Llamamos a esto principio de "persistencia políglota".


Patrón de base de datos por servicio



¿Un ser vicio puede tener una sola base de datos? Veamos la siguiente sección.


Arquitectura lógica vs Arquitectura física

La creación de microservicios no requiere el uso de ninguna tecnología específica. Por ejemplo, los contenedores de Docker no son obligatorios para crar una arquitectura basada en microservicios. Esos microservicios también se pueden ejecutar como procesos sin formato. Los microservicios son una arquitectura lógica.

La arquitectura lógica y los límites lógicos de un sistema no se asignan necesariamente uno a uno a la arquitectura física o de implementación. Esto puede suceder, pero a menudo no es así.

Por tanto, un microservicio o contexto limitado empresarial es una arquitectura lógica que podría coincidir (o no) con la arquitectura física. Lo importante es que un microservicio o contexto limitado empresarial debe ser autónomo y permitir que el código y el estado ser versionen, implementen y escalen de forma independiente.






Aplicando el patrón Clear Architecture a un microservicio

Session 4: 2h39m

Antecedentes 

En los últimos años hemos visto una amplia gama de ideas con respecto a la arquitectura de los sistemas. Estos incluyen:
  • Hexagonal Architecture (a.k.a. Ports and Adapters) por Alistair Cockburn y adoptado por Steve Freeman y Nat Pryce en su libro Growing Object Oriented Software.
  • Arquitectura de cebolla por Jeffrey Palermo.
  • Screaming Architecture de un blog de Robert C. Martin
  • DCI de James Coplien y Trygve Reenskaug.
  • BCE por Ivar Jacobson de su libro Object Oriented Software Engineering: A Use-Case Driven Approach.
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

Arquitectura Hexagonal

  • La arquitectura hexagonal, también conocida como patrón de puertos y adaptadores intentan mantener toda la lógica y los modelos de negocios en un solo lugar y todo los demás depende de esto en lugar de lo contrario.
  • Si miramos desde cualquier perspectiva de capas de aplicación, las dependencias serían hacia el dominio desde el controlador/interfaz y la persistencia en lugar de la arquitectura en capas que solemos hacer en nuestros proyectos. De esta manera  hacemos que estos hexágonos sean independientes y puedan relacionarse con el contexto acotado en términos DDD. Al usar la analogía anterior, arquitectura se llamaría "Plugin-Architecture"; Su modelo base permanece intacto y puede ampliar aún más las funcionalidades colocando más implementaciones de plugin que se adhieran a las mismas interfaces.




Objetivo de Clean Architecture

El objetivo principal de Clean Architecture es permitir que el negocio se adapte a la tecnología e interfaces cambiantes. Si bien Internet puede pasar del escritorio al móvil, o del móvil al asistente virtual, el negocio principal sigue siendo el mismo. Particularmente en el acelerado mundo de los marcos de Javascript y las bibliotecas front-end, el uso de una arquitectura limpia puede salvarlo del patrón común de acoplar estrechamente la lógica empresarial a la capa de presentación o al marco.

Características de Clean Architecture

  • Se trata de la separación de responsabilidades. Dividir el software en capas.
  • Debe ser independiente de los Framworks
  • Debe ser testeable
  • Debe ser independiente de la interfaz de usuario
  • Debe ser independiente de la base de datos
  • Debe ser independiente de las dependencias de erd party
  • Avanzando hacia adentro, el nivel de abstracción y el aumento de políticas.
  • El círculo más interno es el más general/nivel más alto
  • Los círculos internos son políticas
  • Los círculos exteriores son mecanismos
  • Los círculos internos no pueden depender de los círculos externos
  • Los círculos exteriores no pueden influir en los círculos internos.

Componentes de Clean Architecture

Entidades

  • Las entidades deben ser utilizables por muchas aplicaciones (reglas de negocio críticas) y no deben verse afectadas por nada más que un cambio en la regla de negocio crítica en sí. 
  • Encapsulan las reglas más generales/de alto nivel.

Casos de uso

  • Los casos de uso son reglas de negocio específicas de la aplicación.
    • Los cambios no deben afectar a las Entidades
    • Los cambios no deben verse afectados por la infraestructura, como una base de datos.
  • Los casos de uso orquestan el flujo de datos que entran/salen de las entidades y dirigen a las entidades a usar sus reglas de negocio críticias para lograr el caso de uso.

Adaptadores de interfaz

  • Convierten datos de capas de datos en capas de casos de uso o capas de entidad. Los presentadores, las vistas y los controladores pertenecen aquí.
  • Ningún código más avanzado en (casos de uso, entidades) debe tener ningún conocimiento de la base de datos.

Frameworks & Drivers

  • Estos son el pegamento que engancha las diversas capas hacia arriba.
  • Los detalles de la infraestructura viven aquí.
  • No estás escribiendo mucho de código, es decir, usamos SQL Server, perno lo escribimos.

Interacción de Clean Architecture

Cruzando límites

  • El flujo de control pasó del controlador, a través del caso de uso de la aplicación, luego al presentador. 
  • Las dependencias del código fuente apuntan hacia los casos de uso.
  • Principio de inversión de dependencias
    • El caso de uso necesita llamar a un presentador, hacerlo violaría la regla de dependencia: los círulos internos no pueden llamar (o conocer) círculos externos.
      • El caso de uso necesitaría llamar a una interfaz
        • La implementación de esta interfaz sería proporcionada por la capa de adaptador de interfaz: así es como se invierte la dependencia.
          • Este mismo tipo de inversión de control se utiliza en toda la arquitectura para invertir el flujo de control.

Datos cruzando fronteras

  • Normalmente, los datos que cruzan los límites consisten en estructuras de datos simples.
  • No pase objetos de entidad ni filas de datos. Esto violaría las reglas de dependencia.
  • Los datos se pasan en el formato que sea más conveniente para el círculo/capa interna.
  • Estas son estructuras de datos aisladas y simples.
    • Lo que significa que nuestros DTO necesarios para cruzar los límites deben pertenecer al círculo interno, o al menos a su definición (interfaz, clase abstracta).

Ejemplo de código



Links

Monday, August 12, 2024

Introducción al patrón Bounded Context

¿Qué enfoque utilizar para la descomposición?

  • Transaction Script (procedural): toda la lógica resida en scripts que normalmente están en BD.
  • Table Module / Active Record (Orientado a los datos): la lógica de negocio está acoplada a las tablas de la BD.
  • Domain Driven Design (Orientado al negocio): Manejar objetos de negocio







  • Para microservicios, nos vamos a centra en DDD.
  • DDD es una forma de pensar (mindset) las cosas. No solo se aplica al código, sino a difernetes áreas del desarrollo de software (análisis, diseño, pruebas, etc.). 
  • Tanto los enfoques "Transaction Script" y "Table Module" le dan mucha responsabilidad a la BD lo cual te deja ligado a la tecnología (alto acoplamiento).

Modelo de dominio

El modelo de dominio no es una representación directa de las de una BD. Múltiples tablas pueden decantar en una sola entidad de negocio. La recomendación es no poner lógica en la BD. Sin embargo, puede haber excepciones, como la reportería.


Características de DDD

  • Software que modela dominios del mundo real (Expertos en dominios y desarrolladores de software)
  • Muchas herramienas y técnicas
  • Concept of bounded contexts
  • El dominio consta de múltiples contextos delimitados (Cada BC representa una función de dominio)
  • El Bounded Context fomenta bajo acoplamiento y alta cohesión.

Ventajas del modelo de dominio

  • Gestionar complejidad
  • Aprovecha los patrones de diseño
  • Hablar el lenguaje del negocio
  • Abstrae el equema de BD poco bonitas (nombres feos)
  • Facilitación para equipos grandes
  • Reutilizable

Desventajas del modelo de dominio

  • Curva de aprendizaje
  • Diseño que consume mucho tiempo
  • Compromiso a largo plazo
  • Gastos generales de mapeo de BD

Bounded Context

Una responsabilidad específica impuesta por un límite explícito.
  • Identificar el concepto de dominio principal.
  • Modelos internos (conceptos de apoyo)
  • Cada BC tiene una interfaz explícita (entradas y salidas)
  • Modelos compartidos para la comunicación
  • Microservicio = Bounded Context
    • Pertenece a un equipo
    • Dueño de su propio almacén de datos
    • Contratos (interfaces)
  • Bounded Context es lógica
  • Contextos externos (fuera del contexto)

Lenguaje Ubicuo

Lenguaje que pertenece a una función de dominio específica (Bounded Context). También utilizado por todos los miembros del equipo para conectar todas las actividades del equipo con el software.

  • Para comunicarse correctamente con el experto de dominio. 
  • Cada subdominio va a manejar su lenguaje de negocio.
  • Como arquitectos tenemos que hablar el lenguaje del negocio.

Bounded Context y Lenguaje Ubicuo

  • El concepto principal define el lenguaje de dominio, es decir, el objetivo principal.
  • Se usa como filtro de Bounded Context
    • Conceptos en contexto
    • Conceptos contexto externos (fuera del contexto)
  • Quienes definen el lenguaje
    • Expernos en dominios
    • Desarrolladores de software
  • Se recomienda usar un diccionar de negocio

Contextos sin límites

  • Enfoque usualmente utilizado en el desarrollo tradicional.
  • Se viola el principio de responsabilidad única


Ejemplo: Dominio de envíos

Establezco los dominios que forman parte de mi proceso de negocio:



Conceptos principales y conceptos de soporte.


Bounded Context como técnica
  • Identificar los aspectos/conceptos clave del dominio 
  • Los conceptos forman los Bounded Contexts
  • El concepto principal forma un lenguaje ubicuo
  • Renombrar conceptos/modelos de soporte
  • Renombrar los conceptos LU a natruales
  • Mover a contextos externos (fuera de contexto) conceptos/modelos
  • No es parte del lenguaje ubicuo
  • Eliminar conceptos fuera de alcance
  • Los conceptos individuales indican integración
  • Integración con otros Bounded Context

Identificando el core (conceptos principales)



Renombrar conceptos
Conceptos fuera de contexto

Conceptos únicos indican integración


Bounded Context a Microservicios








¿Cuándo componer o realizar agregación de servicios?
  • Servicios combinados
  • Uso de descomposición (método de Bounded Context)
  • Razones para la integración
    • Informes
    • Funcionalidad mejorada
    • Usabilidad para clientes
    • Performance

Granularidad de servicios
  • Realización de las funciones de un proceso mediante la implementación de una gran cantidad de servicios detallados conduce a la reducción de los esfuerzos de desarrollo y mantenimiento. Además, un mayor potencial de reutlización de los servicios se puede lograr.
  • Sin embargo, al mismo tiempo los costes de composición de (muchos) servicios aumentan. Cuanto más fina se la granualidad para realizar las funciones de un proceso, mayor es el número de servicios y más esfuerzo tiene que ser gastado en componerlos. Por el contrario, los servicios de grano muy grueso tienen las desventajas de mayores costos de implementación y menor potencial de reutilización.
Granularidad de servicios - Teraservices
  • Los teraservices son lo opuesto a los microservicios
  • El diseño de teraservices implica una especie de servicio monolítico. Los Teraservices requieren dos terabytes de memoria o más. Estos servicios se pueden utilizar cuando los servicios solo se requieren en la memoria y tienen un uso elevado.
  • Estos servicios son bastante costosos en entornos de nube debido a la memoria necesaria, pero el costo adicional se puede compensar cambiando de servidores de cuatro núcleos a servidores de doble núcleo.
Granularidad de servicios - Microservices
  • En los Microservices, los componentes de diseño no se agrupan y tienen acoplamientos flexibles.
  • Cada servicio tiene sus propias capas y base de datos, y se agrupan en un archivo independiente para todos los demas.
  • Todos estos servicios implementados proporcionan sus API específicas, como Clientes o Reservas. Estas API están listas para consumirse. Incluso la interfaz de usuario también se implmenta por separado y se diseña mediante el usuo de los servicios de la interfaz de usuario.
  • Por esta razón, los microservicios proporcionan varias ventajas sobre su contraparte monolítica.
Granularidad de servicios - Nanoservices
  • Los microservicios que son especialmente pequeños o detallados se denominan nanoservicios.
  • Un patrón de nanoservicios es realmente un antipatrón.
  • En el caso de los nanoservicios, las sobrecargas, como las actividades de comunicación y mantenimiento superar su utilidad.
  • Se deben evitar los nanoservicios. Un ejemplo de un patrón de nanoservicios (anti) sería crear un servicio independiente para cada taba de base de datos y exponer su operación CRUD mediante eventos o una API REST.

Granularidad de servicios - Consejos para construir según TOGAF
  • Supongamos que hay una línea horizontal imaginaria (eje x), que representa la línea de granularidad; el nivel adecuado determinado para MSA.
  • Los servicios que están más cerca, o alrededor de esta línea (servicios dentro de la caja punteada), son buenos microservicios; aquellos que están muy por encima de esta tendencia de línea hacia la exhibición de características de los monolitos, y los que caen muy por debajo de la tendencia de línea hacia la exhibición de características de nanoservicios.
  • Los problemas con los monolitos incluyen:
    • Incluso los cambios pequeños y menores requieren la reconstrucción de toda la base de código y la re-implementación de la nueva compilación.
    • Los ciclos de cambio (para varias funcioens y características) tendrán que estar unidos entre sí, lo que provocará una dependencia no deseada.
    • Lograr una estructura modular dentro de un monolito es difícil de aplicar.
    • El escalado se logra replicando toda la aplicación (aunque funcioens específicas pueden tener diferentes requisitos de escalabilidad).
  • Los problemas con los nanoservicios incluyen:
    • Las llamadas remotas son costosas (desde una perspectiva de rendimiento).
    • La comunicación entre los servicios se vuelve habladora, lo que resulta en un sistema subóptimo. 
    • La explosión inmanejable de los servicios puede dar lugar a la proliferación de servicios, a una gobernanza desafiante.



Aplicando el patrón DDD a un microservicio



Notas:
  • El ValueObject sirve para hacer validaciones que no son de negocio, por ejemplo, las validaciones de formato.
  • Las validaciones de negocio son parte de la entidad.

Links




Características de una arquitectura de microservicios

Arquitectura de microservicios

  • El estilo arquitectónico de microservicio es un enfoque para desarrollar una sola aplicación como un conjunto de servicios pequeños, cada uno que se ejecuta en su propio proceso y se comunica con mecanismos ligeros, a menudo una API de recursos HTTP.
  • Estos servicios se basan en las capacidades del negocio y se pueden implementar de forma independiente mediante maquinaria de implementación totalmente automatizada.
  • Hay un mínim de gestión centralizada de estos servicios, que puede escribirse en diferentes lenguajes de programación y utilizar diferentes tecnologías de almacenamiento de datos.

Característica de diseño

Componentes a través de servicios

  • Es mejor utilizar algún paradigma del mundo real, como un usuario se refiere a un "Sistema estéreo". Lo mueven, lo fijan en otro lugar. Mueva, quite y conecte diferentes altavoces.
  • Básicamente un componente es algo que es actualizable y reemplazable de forma independiente.
  • La diferencia es simplemente que los servicios no se incorporan directamente a su código base, sino que se llaman a través de llamadas remotas.

Organizado en torno a las capacidades de negocio

  • Muchas organizaciones estructuran sus equipos en torno a la tecnología: especialistas de interfaz de usuario, equipo de middleware, DBAs.
  • Más bien, con los microservicios, las personas deben organizarse en torno a las capacidades empresariales dentro de los equipos multifuncionales: como el "equipo de envío", el "equipo de pedidos".
  • Microservicios se trata mucho más de la organización del equipo que de la arquitectura de software. La arquitectura y la organización del equipo siemper están muy unidas.

Endpoints inteligentes y pipes tontos

  • Es una práctica común utilizar infraestructura de red inteligente como ESB que contiene lógica sobre cómo tratar ciertos mensajes de red y cómo entutarlos.
  • En su lugar, los microservicios facilitan los pipes tontos y los endpoints/aplicaciones inteligentes.
  • El problema es que los pipes inteligentes (es decir, ESB) conducen a problemas con la entrega continua, ya que no se pueden controlar o integrar fácilmente en un pipe grande.
  • Además, crea dependencias con la propia aplicación, lo que significa que cuando decide actualizar el endpoint o servicio, a menudo también tiene que realizar algún trabajo en el ESB.

Gestión descentralizada de datos

  • Normalmente, en un sistema monolito hay una enorme base de datos donde se almacenan todos los datos. A menudo incluso hay varios monolitos que se conectan a la misma base de datos.
  • En un enfoque orientado a servicios, cada servicio obtiene su propia base de datos y los datos no se comparten directamente con otros. Compartir tiene que pasar por el servicio que envuelve los datos. Esto conduce a una gran flexibilidad beneficiosa por parte del servicio, ya que puede decidir qué tecnología adoptar, qué sistema DBMS, etc.

Automatización de la infraestructura

  • La entrega continua es una necesidad, así como mecanimos automatizados para el aprovisionamiento de máquinas, para implementación, pruebas, etc.

Diseño para fallos

  • Inevitablemente se tiene que diseñar para el error, ya que los microservicios fallarán, incluso con frecuencia.
  • Netflix es famoso por llevar esto al extremo. Tienen un "Chaos Monkey" que se ejecuta sobre su sistema de producción durante el día y cierra al azar los servicios.
  • Aunque muchas personas tienden a abstraer y ocultar llamadas remotas, no puede esperar que funcionen como llamadas normales. Espere que fracasen en lugar de tener éxito. Ley de Murphy.


Características de gestión

Productos no proyectos

  • La mayoría de los esfuerzos de desarrollo de aplicaciones que vemos utilizan un modelo de proyecto: donde el objetivo es entregar algún software que luego se considera completado. Al finalizar, el software se entrega a una organización de mantenimiento y el equipo del proyecto que lo creó se disuelve.
  • Los defensores de microservicios tienden a evitar este modelo, prefiriendo en su lugar la noción de que un equipo debe poseer un producto a lo largo de toda su vida útil.
  • Una inspiración común para esto es la noción de Amazon de "usted construye, usted lo ejecuta" donde un equipo de desarrollo asume toda la responsabilidad por el software en producción. Esto lleva a los desarrolladores al contacto diario con el modoen que su software se comporta en producción y aumenta el contacto con sus usuarios, ya que tienen que asumir al menos parte de la carga de soporte.


Gobernanza descentralizada (Independencia tecnológica)

  • Una de las consecuencias de la gobernanza centralizada es la tendencia a estandarizarse en plataformas tecnológicas únicas. La experiencia demuestra que este enfoque es restrictivo - no todos los problemas son un clavo y no todas las soluciones un martillo.
  • En lugar de utilizar un conjunto de estándares definidos escritos en algún lugar en papel prefieren la idea de producir herramientas útiles que otros desarrolladores pueden utilizar para resolver problemas similares a los que están enfrentando. No tenemos que amarrarnos a única tecnología.

Diseño evolutivo

  • Cada vez que intenta dividir un sistema de software en componentes, se enfrenta a la decisión de cómo dividir las piezas ¿cúales son los principios sobre los que decidimos cortar nuestra aplicación? La propiedad clave de un componente es la noción de reemplazo independiente y capacidad de actualización.
  • Este énfasis en la reemplazabilidad es un caso especial de un principio más general del diseño modular. Si se encuentra cambiando repetidamente dos servicios juntos, eso es una señal de que deben combinarse.


Links

Contenerización

Nota: Podemos hacer microservicios sin contenedores. 

Virtualización

Estrictitamente hablando, contenerización no es virtualización, sin embargo se lo considera así con fines de comparación.




Docker

  • Docker es un proyecto de código abierto para automatizar la implementación de aplicaciones como contenedores portátiles y autosuficientes que se pueden ejecutar en la nube o localmente. Docker es también una empresa que promueve e impulsa esta tecnología, en colaboración con proveedores de la nube, Linux y Windows, incluido Microsoft. En pocas palabras, Docker es una tecnología y una marca.
  • Los contenedores permiten portabilizar mi aplicación y lo puedo desplegar en mi datacenter o en la nube.

  • Hoy en día se recomienda que las aplicaciones sean contenerizadas por su flexibilidad.
  • La arquitectura de Docker es de la siguiente forma:

  • ¿Es recomendable contenerizar una BD?
    • Si es un proceso batch, entonces se podría contenerizar. Si se trata de una aplicación pequeña, entonces si puede ser adecuado contenerizarla pues dicha aplicación no tendrá mucha carga.
    • Si tu BD es el core de tu sistema, entonces no lo contenerices, mejor utiliza un fierro exclusivo. No olvidar que la contenerización comparte infraestructura. Si se trata de una aplicación grande, entonces la BD puede ser "clasterizada", es decir, mi BD estará repartida en múltiples infraestructuras, pero lógicamente solo será una sola BD.

Links

Sunday, August 4, 2024

Principales patrones de microservicios

Patrones a utilizar para el diseño de microservicios



  • En el desarrollo de software empresarial a gran escala moderno, la arquitectura de microservicios puede ayudar a escalar el desarrollo con muchas ventajas a largo plazo. Pero la arquitectura de microservicios no es una solución mágica que se pueda usar en todos los casos de uso. Si se utiliza en el tipo incorrecto de aplicación, la arquitectura de microservicios puede dar más dolores que ganancias.
  • El equipo de desarrollo que desea adoptar la arquitectura de microservicios debe seguir un conjunto de procedimientos recomendados y usar un conjunto de patrones de diseño reutilizables y reforzados en batalla.
  • El patrón de diseño más importante en la arquitectura de microservicios es "Database per Service". La implementación de este patrón de diseño es un desafío y necesita varios otros patrones de diseño estrechamente relacionados (Event Sourcing, CQRS, Saga).
  • En las aplicaciones empresariales típicas con varios clientes (Web, móvil, escritorio, Smart Devices), las comunicaciones entre el cliente y los microservicios pueden ser conversadores y pueden requerir control central con seguridad agregada. Los patrones de diseño Backends For Front-end (BFF) y API Gateway son muy útiles en estos escenarios.

Cuando el código funciona, pero no tiene tests: ¿y ahora qué?

Seguramente te ha pasado alguna vez. Te dan acceso al repositorio de un nuevo proyecto. Lo abres con curiosidad, esperas encontrar una estru...