Arquitectura Java

Arquitectura Java para plataformas que tienen que durar

Cómo se estructura una aplicación Java empresarial: qué decisiones condicionan los próximos años, cuándo un monolito modular es mejor que los microservicios y cómo evitar que el dominio acabe atado al framework.

Punto de partida

Arquitectura no es elegir tecnología

Es decidir qué depende de qué. Esa decisión es la que resulta cara de revertir cuando el sistema ya está en producción.

La arquitectura Java es el conjunto de decisiones estructurales que determinan cómo se organiza una aplicación empresarial: la separación entre dominio e infraestructura, los límites entre módulos o servicios, los contratos de integración, la estrategia de persistencia y el modelo de despliegue.

Escoger Spring Boot, Quarkus, PostgreSQL o Kafka son decisiones importantes, pero reversibles con un esfuerzo acotado. Las decisiones verdaderamente arquitectónicas son otras: dónde están los límites del dominio, quién puede escribir en qué datos y qué depende de qué.

Una arquitectura Java sana se reconoce por una propiedad concreta: se puede cambiar la base de datos, el broker de mensajería o la capa de API sin tocar una sola clase que contenga reglas de negocio. Si ese cambio obliga a reescribir el dominio, la arquitectura ya está imponiendo un coste sobre cada evolución futura.

Punto de equilibrio

Monolito modular por defecto, microservicios por necesidad

Un monolito modular con arquitectura hexagonal es la opción correcta de partida para la mayoría de plataformas Java empresariales.

Aísla el dominio de los frameworks, permite ejecutar la lógica de negocio en pruebas sin levantar infraestructura y mantiene abierta la posibilidad de extraer servicios cuando exista una razón para hacerlo.

El razonamiento es de coste. Un monolito modular paga el precio de la disciplina en el diseño; una arquitectura de microservicios paga, además, un coste operativo permanente: despliegues coordinados, trazabilidad distribuida, consistencia eventual, gestión de fallos parciales y un entorno local que deja de ser trivial. Ese precio solo se justifica cuando compra algo concreto.

Autonomía de equipos

Varios equipos que necesitan desplegar sin coordinarse entre sí ni competir por el mismo repositorio.

Escalado divergente

Componentes con perfiles de carga tan distintos que escalar el conjunto resulta inviable o desproporcionado.

Aislamiento regulatorio

Datos o procesos sujetos a requisitos de cumplimiento que exigen fronteras físicas entre sistemas.

Ciclos de vida distintos

Partes del sistema que evolucionan a ritmos incompatibles y se estorban dentro del mismo despliegue.

Fuera de estos cuatro casos, la modularidad interna bien impuesta ofrece casi todas las ventajas sin el coste de la red.

Migración

Dividir un monolito resuelve un problema organizativo

Conviene migrar cuando el cuello de botella es organizativo, no técnico: equipos que se bloquean entre sí en el mismo repositorio, ciclos de release que no pueden desacoplarse o componentes cuyo escalado independiente resulta imprescindible.

Si el problema es rendimiento o deuda técnica dentro de un único equipo, dividir el sistema casi siempre lo empeora: cada llamada a un método se convierte en una llamada de red con latencia, fallos parciales y necesidad de reintentos idempotentes. La deuda técnica no desaparece al repartirla entre repositorios; se multiplica por el número de despliegues.

Cuando la migración está justificada, el patrón que funciona es el strangler fig: colocar una fachada estable delante del sistema actual y extraer capacidades de una en una, empezando por las que tienen menos dependencias de datos. Cada extracción se despliega y se valida en producción antes de abordar la siguiente. La reescritura completa con un único corte de migración es la vía que más proyectos de modernización ha hundido.

Patrones

Hexagonal frente a capas: la diferencia se ve en las pruebas

En una arquitectura en capas las dependencias fluyen hacia abajo y el dominio acaba dependiendo de la capa de persistencia, de modo que un cambio de ORM o de base de datos se propaga hasta las reglas de negocio. En la arquitectura hexagonal las dependencias apuntan todas hacia el dominio: persistencia, mensajería y API son adaptadores que implementan puertos definidos por el propio dominio.

Con arquitectura en capas, probar una regla de negocio suele requerir levantar un contexto de Spring y una base de datos en memoria. Con arquitectura hexagonal, esa misma regla se prueba con objetos planos y dobles de prueba en milisegundos, porque el dominio no conoce ninguna tecnología.

Desarrollo ambos enfoques en detalle en la guía de arquitectura hexagonal desde cero, con el código de los puertos y adaptadores sobre Spring Boot.

Diagnóstico

Cinco señales de que la arquitectura está bien planteada

Todas comprobables sin entrar a valorar el estilo del código, y todas ellas parte de lo que evalúo en una auditoría técnica.

El dominio se prueba solo

Las pruebas de negocio se ejecutan sin base de datos ni contexto del framework. Si lo necesitan, el dominio está acoplado.

Los cambios están localizados

Una funcionalidad nueva toca pocos módulos. Si cada cambio se propaga por todo el sistema, los límites están mal trazados.

El esquema no manda

Un cambio de esquema no rompe el dominio: la persistencia se adapta al modelo, y no al revés.

Los fallos se diagnostican

Existe trazabilidad de extremo a extremo. Un problema en producción se localiza con datos, no reproduciéndolo a mano.

El proyecto se explica solo

Un desarrollador nuevo es productivo en días porque la estructura del código refleja el negocio.

Estas cinco señales son las que reviso en una auditoría técnica, junto con el análisis de deuda técnica, rendimiento y riesgos de escalabilidad.

Preguntas frecuentes

Dudas habituales sobre arquitectura Java en proyectos empresariales.

¿Qué es la arquitectura Java?

La arquitectura Java es el conjunto de decisiones estructurales que determinan cómo se organiza una aplicación empresarial construida sobre la plataforma Java: la separación entre dominio e infraestructura, los límites entre módulos o servicios, los contratos de integración, la estrategia de persistencia y el modelo de despliegue. No consiste en elegir frameworks, sino en definir restricciones que mantengan el sistema comprensible y modificable a medida que crece.

¿Qué arquitectura conviene para una aplicación Java empresarial?

Para la mayoría de aplicaciones Java empresariales, un monolito modular con arquitectura hexagonal es la opción correcta de partida: aísla el dominio de los frameworks, permite probar la lógica de negocio sin infraestructura y mantiene abierta la posibilidad de extraer servicios más adelante. Los microservicios solo compensan cuando existen razones organizativas o de escalado independiente reales, porque añaden un coste operativo permanente en despliegue, observabilidad y consistencia de datos.

¿Cuándo conviene migrar un monolito Java a microservicios?

Conviene migrar cuando el cuello de botella es organizativo, no técnico: varios equipos bloqueándose entre sí en el mismo repositorio, ciclos de release que no pueden desacoplarse o componentes con perfiles de escalado radicalmente distintos. Si el problema es rendimiento o deuda técnica dentro de un único equipo, dividir el sistema suele empeorarlo, porque convierte llamadas a métodos en llamadas de red con fallos parciales, latencia y necesidad de consistencia eventual.

¿Qué diferencia hay entre arquitectura hexagonal y arquitectura en capas?

En una arquitectura en capas las dependencias fluyen hacia abajo y el dominio termina dependiendo de la capa de persistencia, de modo que un cambio de base de datos u ORM se propaga hasta las reglas de negocio. En la arquitectura hexagonal todas las dependencias apuntan hacia el dominio: la persistencia, la mensajería y la API son adaptadores que implementan puertos definidos por el propio dominio, que no conoce ninguna tecnología concreta.

¿Qué versión de Java conviene usar en un proyecto nuevo?

En un proyecto nuevo conviene partir de la última versión LTS soportada por el ecosistema del proyecto. Java 21 aporta virtual threads, que simplifican radicalmente la concurrencia en servicios con mucha espera de entrada/salida, además de pattern matching y records, que reducen el código repetitivo al modelar el dominio. Mantenerse en versiones antiguas rara vez ahorra trabajo: acumula una migración mayor y cierra el acceso a mejoras de rendimiento del propio runtime.

¿Necesitas definir o revisar la arquitectura de tu plataforma Java?

Analizo el sistema actual, identifico los riesgos estructurales y propongo una arquitectura objetivo con un plan de transición realista.