01 - Arquitecturas de software
Una aplicación puede clasificarse según distintos criterios. Por ejemplo, puede desplegarse como monolito modular y organizarse internamente por capas con inversión de dependencias.
1. Principios de arquitectura limpia
La arquitectura limpia protege las reglas del negocio de los detalles técnicos y externos:
| Principio | Idea clave |
|---|---|
| Independencia de frameworks | El framework es una herramienta, no el centro de la aplicación |
| Testeable | Las reglas se prueban sin levantar interfaz, base de datos ni framework |
| Independencia de la interfaz | La misma lógica puede exponerse mediante interfaces distintas |
| Independencia de la base de datos | Se puede cambiar la persistencia sin reescribir las reglas |
| Independencia de agentes externos | El negocio no depende de servicios externos concretos |
| Regla de dependencia | El código depende hacia las políticas de negocio, no hacia los detalles |
| Inversión de dependencias (DIP) | El núcleo define las abstracciones que necesita; los detalles externos las implementan |
2. Organización interna
2.1 Arquitectura por capas
La arquitectura por capas agrupa componentes por responsabilidad. En esta arquitectura de referencia:
| Capa | Componentes y responsabilidad |
|---|---|
controller | Controladores y DTO de entrada y salida; comunica la aplicación con clientes externos |
domain | Interfaces e implementaciones de servicios, modelos e interfaces de repositorio; contiene las reglas del negocio |
persistence | Implementaciones de repositorio y DAO; accede a la base de datos |
Service y Repository son interfaces; ServiceImpl y RepositoryImpl las implementan. DAO también se separa en interfaz e implementación, ambas dentro de persistence.
domain define la interfaz Repository que necesita; persistence la implementa. Esta inversión de dependencias evita que el dominio dependa de la tecnología de persistencia y aplica un principio de arquitectura limpia.
2.2 Arquitectura hexagonal (Ports and Adapters)
La arquitectura hexagonal separa el núcleo de los sistemas externos mediante puertos (interfaces que definen cómo se usa o qué necesita el núcleo) y adaptadores (componentes que conectan esas interfaces con tecnologías concretas).
2.3 Arquitectura de cebolla
La arquitectura de cebolla organiza el sistema en anillos alrededor del dominio. Las dependencias apuntan desde los anillos externos hacia el núcleo.
| Enfoque | Idea principal | Observación |
|---|---|---|
| Capas | Agrupa por responsabilidad y delega entre capas | Evitar que el dominio dependa directamente de tecnologías |
| Hexagonal | Aísla el núcleo mediante puertos y adaptadores | Facilita sustituir tecnologías y probar el núcleo |
| Cebolla | Organiza el sistema en anillos alrededor del dominio | Las dependencias apuntan hacia el centro |
3. Arquitectura de despliegue
La arquitectura de despliegue describe cómo se empaqueta, ejecuta y despliega una aplicación; es un criterio distinto de su organización interna.
3.1 Monolito, monolito modular y microservicios
| Estilo | Despliegue | Límites y datos | Coste o ventaja |
|---|---|---|---|
| Monolito | Una aplicación desplegable | Los componentes pueden compartir proceso y almacenamiento | Operación sencilla; puede crecer con alto acoplamiento |
| Monolito modular | Una aplicación desplegable | Módulos con límites y APIs internas explícitas | Modularidad sin multiplicar despliegues |
| Microservicios | Varios servicios desplegables | Cada servicio controla sus datos y se comunica por red | Despliegue independiente; más complejidad operativa |
Un monolito no implica código desordenado y puede ser adecuado para una aplicación pequeña, como un CRUD. En un monolito modular, los módulos colaboran dentro del mismo proceso mediante sus APIs públicas.
3.2 Tipos de comunicación
| Tipo | Funcionamiento | Característica |
|---|---|---|
| Síncrona | El emisor hace una llamada y espera una respuesta | Depende de la disponibilidad y el tiempo de respuesta del receptor |
| Asíncrona | El emisor publica un mensaje o evento para que se procese después | Desacopla temporalmente; puede haber retrasos o entregas duplicadas |
Los módulos de una aplicación pueden comunicarse mediante llamadas a APIs internas o eventos. Los microservicios se comunican por red, mediante HTTP o un intermediario de mensajes como RabbitMQ o Kafka.
Los eventos entre módulos no implican comunicación de red ni crean por sí solos aislamiento o una transacción independiente. La comunicación distribuida debe contemplar fallos de red.