Hey dev, esta vez toca un artículo y reflexión incluída, además espero que te ayude a entender un punto crucial cuando se trata de Arquitectura de software, y como es usual, no se habla mucho de este tema.
¿Alguna vez has tenido una discusión técnica donde alguien dice "usamos una arquitectura de microservicios" y otro responde "sí, pero con principios Clean Architecture"? ¿Qué pasó aquí? ¿Es que son excluyentes ambas arquitecturas? Para comenzar, nos estamos refiriendo a lo mismo? La respuesta es no, y entender por qué es la clave para pensar como un verdadero arquitecto de software.
La confusión surge de hablar de la arquitectura como un concepto único, cuando en realidad se compone de distintas vistas o para entenderlo mejor podemos llamarlas "perspectivas" o niveles que debemos manejar simultáneamente.
Yo me he podido percatar de esto de forma empírica a través de los varios años que ya llevo en esto, sin embargo no es algo que se me ha ocurrido a mi así que a continuación te voy a dar una fuente seria que habla de esto.
El libro de referencia como "Software Architecture in Practice" de Bass, Clements y Kazman sienta desde sus primeras páginas las bases para todo esto que te estoy contando.

El Hallazgo: Las Tres Estructuras Clave
En el Capítulo 1 de la cuarta edición de este libro canónico, se encuentra la esencia (Sección 1.4, "Summary"):
"The software architecture of a system is the set of structures needed to reason about the system. These structures comprise software elements, relations among them, and properties of both."
El libro identifica tres categorías de estructuras primarias:
- Estructuras de Módulo (module structures): Muestran el sistema como un conjunto de unidades de código o datos que hay que construir o adquirir. Piensa en paquetes, clases, dependencias de compilación y responsabilidades. Es la visión estática del código.
- Estructuras de Componente y Conector (C&C component-and-connector): Muestran el sistema como un conjunto de elementos que tienen comportamiento en tiempo de ejecución (componentes) e interacciones (conectores). Piensa en servicios, APIs, mensajes, flujos de datos y procesos. Es la visión dinámica del sistema en acción.
- Estructuras de Asignación (allocation structures): Muestran cómo los elementos de las estructuras anteriores se relacionan con el mundo no software: hardware, equipos de desarrollo, etc.
Estas tres estructuras son los "puntos de palanca" de la arquitectura. Cada una nos permite influir en diferentes atributos de calidad (como la mantenibilidad o el rendimiento) y comunicarnos con distintos stakeholders (desde developers hasta managers o sysadmins).

Traduciendo a Términos Cotidianos
Aterricemos la teoría.
Para simplificar, podemos agrupar estas estructuras en niveles de abstracción o perspectivas con los que todo desarrollador debe familiarizarse.
1. Nivel de Sistema (Runtime) - La Vista "Componente y Conector" (C&C)
Este es el nivel del "Qué hace el sistema y cómo interactúa cuando está encendido".
Responde a preguntas como:
- ¿Cómo se comunican las partes entre sí?
- ¿Qué protocolos se usan (HTTP, gRPC, mensajes)?
- ¿Cómo se distribuye la carga?
- ¿Dónde están los cuellos de botella?
Aquí es donde viven los patrones arquitectónicos de alto nivel:
- Microservicios: Un conjunto de componentes (servicios) independientes desplegables, conectados por APIs.
- Arquitectura Orientada a Servicios (SOA): Un precursor de los microservicios con un enfoque en la integración empresarial.
- Monolito: Un único componente de ejecución que contiene toda la lógica. (Sí, un monolito es también una opción de arquitectura a nivel de sistema C&C).
- Event-Driven Architecture (EDA): Event-Driven Architecture (EDA): donde los componentes se comunican principalmente mediante la producción y el consumo de eventos.
2. Nivel de Módulo/Componente (Estático) - La Vista "Módulo"
Este es el nivel del "Cómo está organizado el código para que yo lo pueda construir, entender y cambiar". Responde a preguntas como:
- ¿Cómo se organizan los paquetes?
- ¿Qué módulo depende de cuál?
- ¿Está el código bien encapsulado?
- ¿Cómo protegemos el dominio de negocio de los detalles técnicos?
Aquí es donde viven las siguientes arquitecturas:
- Arquitectura en Capas (Layered Architecture): El patrón más común. Organiza los módulos en capas (presentación, lógica de negocio, persistencia) con reglas estrictas de dependencia (una capa solo puede depender de la capa inmediatamente inferior).
- Arquitectura Limpia (Clean Architecture): Un conjunto de principios para organizar el código en capas concéntricas, protegiendo la lógica de negocio.
- Arquitectura Hexagonal (Puertos y Adaptadores): Un estilo que aisla el núcleo de la aplicación haciendo que los detalles externos (BD, UI) sean "adaptadores" intercambiables.
- Arquitectura Onion (Cebolla): Muy similar a la Clean Architecture, con un fuerte enfoque en las dependencias hacia el centro (dominio).
- Monolito (otra vez): Un monolito puede tener una mala estructura de módulo (un "big ball of mud") o una excelente estructura de módulo (si aplicas Clean Architecture dentro de él).
3. Ejemplos para la Vista de Asignación - Nivel de Despliegue/Entorno
Esta vista se preocupa por la relación entre el software y el mundo físico/organizacional.
Responde a la pregunta: ¿Dónde se ejecuta el software y quién lo desarrolla?
- Arquitectura Cliente-Servidor: Es aquí donde este patrón muestra su faceta de asignación. Se decide y documenta que el módulo "cliente" se asigna a las máquinas de los usuarios finales, y el módulo "servidor" se asigna a una o más máquinas en un centro de datos.
- Despliegue en Nube (Cloud Deployment): Decisiones sobre cómo se asignan los componentes a recursos de la nube:
- Infraestructura como Código (IaC): Usar Terraform o CloudFormation para definir la asignación de recursos.
- Kubernetes: Asignar los microservicios (de la vista C&C) a Pods, Nodes y Namespaces.
- Serverless/Functions as a Service (FaaS): Asignar funciones individuales (componentes de la vista C&C) a un entorno de ejecución efímero como AWS Lambda.
Ejemplo Práctico Unificado: Sistema de E-Commerce
Para verlo en acción, imaginemos un sistema de e-commerce:
- Vista C&C (Runtime): Usa una arquitectura de Microservicios. Tienes componentes como ServicioCatálogo, ServicioCarrito, ServicioPagos y ServicioEnvios. Se comunican con conectores como APIs REST y mensajes asíncronos (Kafka) para desacoplar procesos.
- Vista de Módulo (Código): Dentro de cada microservicio, usas Clean Architecture. El ServicioPagos tiene módulos bien definidos: Entidades (Pago, Transacción), Casos de Uso (ProcesarPago, Reembolsar) y Adaptadores (Controlador REST, Cliente de Pasarela de Pago, Repositorio de Base de Datos).
- Vista de Asignación (Despliegue): Asignas cada microservicio a un contenedor Docker que se ejecuta en un cluster de Kubernetes en la nube (AWS EKS). Asignas la base de datos a un servicio gestionado (AWS RDS).
La Intersección: Por Qué las Tres Vistas son Críticas
A lo mejor ya te diste cuenta, pero por si aún no lo has notado, el verdadero conocimiento surge cuando entiendes que estas vistas no son excluyentes, sino complementarias y simultáneas. Debes tomar decisiones conscientes para cada una de ellas, y estas decisiones se influyen entre sí.
Imagina que decides usar una Arquitectura de Microservicios (decisión de la vista C&C). Esto te da ventajas en despliegue independiente y escalabilidad. Pero esto solo resuelve el panorama general a nivel de sistema. Ahora, debes tomar más decisiones:
- Decisión de Vista de Módulo: ¿Cómo se organiza el código dentro de cada microservicio?
- Escenario 1 (Mal): Cada microservicio es un micronolito desorganizado (un "espaguetti"). Su estructura de módulo es un caos, con acoplamiento alto y dependencias arbitrarias. Es difícil de testear y mantener, anulando muchas de las ventajas de los microservicios.
- Escenario 2 (Ideal): Dentro de cada microservicio, aplicas Clean Architecture o Hexagonal (decisión de la vista de Módulo). Esto te garantiza que cada servicio sea internamente mantenible, testeable y que su núcleo de negocio esté protegido de los detalles de infraestructura.
- Decisión de Vista de Asignación: ¿Cómo se materializa este sistema en el mundo real?
- Escenario 1 (Inconsistente): Despliegas todos los microservicios de forma manual y diferente, sin un estándar claro.
- Escenario 2 (Ideal): Utilizas contenedores Docker y un orquestador como Kubernetes (decisión de la vista de Asignación) para definir de forma declarativa y reproducible cómo cada componente (microservicio) se despliega, escala y se comunica con la infraestructura. Además, asignas la propiedad de cada servicio a un equipo específico.
Del mismo modo, podrías tener un monolito (decisión de la vista C&C) con una excelente estructura Hexagonal (decisión de la vista de Módulo) y un proceso de despliegue automatizado en un servidor cloud (decisión de la vista de Asignación) que lo haga robusto, fácil de mantener y desplegar, evitando la complejidad inherente de los sistemas distribuidos.
Esto te ha debido volar la cabeza, saber esto resuelve muchas dudas y además estimado dev, te irá muy pero muy bien en una entrevista técnica si mencionas todo esto, al final de cuentas saber estas cosas es lo que marca diferencia entre un developer amateur y un senior o staff.
Conclusión: Piensa en Múltiples Perspectivas
La próxima vez que hables o diseñes una arquitectura, no pienses en una única elección monolítica. Piensa como el marco que has descubierto, haciendo tres preguntas clave:
- Vista de Componente y Conector (Runtime): ¿Qué estilo es el más adecuado para los requisitos de runtime como escalabilidad, rendimiento y confiabilidad? (Microservicios, Event-Driven, Monolito, etc.)
- Vista de Módulo (Construcción): ¿Qué estilo de diseño es el más adecuado para garantizar la mantenibilidad, testabilidad y flexibilidad a largo plazo del código dentro de cada componente? (Clean, Hexagonal, Capas, etc.)
- Vista de Asignación (Despliegue): ¿Cómo relaciono el software con el hardware, la nube y los equipos? ¿Cómo se despliega y opera el sistema? (Kubernetes, Serverless, Equipos por servicio, etc.)
Dominar esta distinción entre vistas te permitirá descomponer problemas arquitectónicos complejos, tomar decisiones de diseño más conscientes y comunicarte con una precisión invaluable. No se trata de elegir un único patrón, sino de orquestar las mejores decisiones para cada una de las tres perspectivas que conforman una arquitectura de software completa.
Si esta entrada te ha encantado dev, compártela!
Créditos de imagen de portada: Basada en Foto de Kev Kindred en Unsplash
