¿Qué es la Arquitectura de Software?
Por qué diseñar a escala implica mucho más que escribir código que funcione, y cómo se organiza este tema en torno a drivers, DDD, estructura del sistema, comunicación, datos, resiliencia, cloud, observability y documentación.
Diseñar software a escala no consiste simplemente en escribir código que funcione. A medida que un sistema crece, aparecen decisiones sobre sus límites, sus dependencias, sus datos, sus comunicaciones, su infraestructura y la forma en que se comporta ante fallos.
Estas decisiones tienen consecuencias que van mucho más allá de una clase o un endpoint. Determinan qué tan fácil es modificar el sistema, cuánto tráfico puede soportar, qué sucede cuando una dependencia deja de responder, cuánto cuesta operarlo y qué tan rápido puede evolucionar.
Una definición utilizable
La definición de referencia es la de Bass, Clements y Kazman en Software Architecture in Practice:
La arquitectura de software de un sistema es el conjunto de estructuras necesarias para razonar sobre él, compuestas por elementos de software, las relaciones entre ellos y las propiedades de ambos.
Vale la pena desarmarla, porque cada parte cumple una función:
- “Estructuras”, en plural. No hay una arquitectura. Hay una estructura de módulos, una de componentes en ejecución, una de despliegue, y sirven para razonar sobre preguntas distintas. Por eso el artículo sobre comunicar decisiones insiste en que cada diagrama responde una pregunta y ninguno las responde todas.
- “Relaciones” y no solo elementos. Saber que existen un servicio de pagos y uno de órdenes no dice nada; qué le pide cada uno al otro, de forma síncrona o asíncrona, es lo que determina el comportamiento del sistema.
- “Propiedades”. Latencia, disponibilidad, consistencia. Son las que convierten una decisión en correcta o incorrecta para este caso.
- “Razonar sobre él”. Es el criterio práctico: si una decisión no cambia cómo razonás sobre el sistema, probablemente no sea arquitectónica.
Una segunda formulación, más informal y muy citada, es la de Ralph Johnson, popularizada por Martin Fowler:
La arquitectura es aquello que la gente considera difícil de cambiar.
No es una definición rigurosa, y por eso complementa bien a la anterior: pone el foco en el costo de revertir. Cambiar el color de un botón es barato; cambiar de una base compartida a una por servicio, con datos en producción, no lo es. Esa asimetría es la que justifica pensar antes de construir.
Qué no es arquitectura
Tres confusiones frecuentes, que este tema evita de forma deliberada:
- Arquitectura no es una lista de tecnologías. “Kubernetes, Kafka y Postgres” no es una arquitectura, es un inventario. La arquitectura son los boundaries y las relaciones; las tecnologías son cómo se implementan, y suelen derivarse de los architectural drivers, no al revés.
- Arquitectura no es diseño de software. El límite es de alcance. Cómo se reparten las responsabilidades entre servicios es arquitectura; cómo se reparten entre clases dentro de uno es diseño, y ahí operan los patrones. Son un continuo, no compartimentos estancos: las dos escalas se rigen por las mismas fuerzas de acoplamiento y cohesión.
- Arquitectura no es una fase. No se termina antes de empezar a codear. Se decide de forma incremental, y las decisiones se revisan cuando cambian los drivers que las justificaron.
Cómo se organiza este tema
- Architectural Drivers — por qué una arquitectura debería derivarse de requisitos y restricciones explícitos, y no de una tecnología elegida de antemano.
- Domain-Driven Design (DDD) — cómo modelar el dominio del negocio con Strategic Design (bounded contexts, ubiquitous language) y Tactical Design (entities, aggregates, domain events).
- Arquitectura del Sistema — cómo dividir y desplegar el sistema: monolith, modular monolith, microservicios y SOA, con sus trade-offs reales.
- Arquitectura de la Aplicación — cómo organizar el código dentro de cada aplicación: slicing horizontal vs. vertical, y arquitecturas domain-centric como Hexagonal, Onion y Clean.
- Communication Patterns — synchronous vs. asynchronous, REST, gRPC, GraphQL, colas y pub/sub.
- Data Architecture — ownership de datos, SQL vs. NoSQL, y cuándo tiene sentido Event Sourcing.
- Resiliencia en Sistemas Distribuidos — timeout, retry, circuit breaker, idempotency, bulkhead, sagas y el resto de los mecanismos para convivir con fallos parciales.
- Arquitectura de Cloud e Infraestructura — compute, networking, regions, autoscaling, IaC y disaster recovery.
- Observability y Reliability Engineering — logs, metrics, traces, y cómo SLI/SLO/SLA convierten la confiabilidad en un objetivo medible.
- Cómo Comunicar Decisiones de Arquitectura — ADRs, diagramas UML y el modelo C4 para que una arquitectura no exista solo en la cabeza de quien la diseñó.
El sistema de ejemplo
Los ejemplos de este tema giran alrededor del dominio de Payments dentro de una plataforma de e-commerce: el tipo de sistema donde disponibilidad, consistencia e idempotency dejan de ser preocupaciones abstractas y se vuelven requisitos concretos con consecuencias en dinero real.
Esa plataforma es AndesShop, el mismo e-commerce que usa como ejemplo el tema de patrones de diseño. La diferencia es la escala de la mirada: allá se resuelven problemas de diseño dentro de una clase; acá se decide dónde van los boundaries entre servicios, quién es dueño de qué dato y qué pasa cuando el proveedor de pagos no responde.
