← Volver a artículos

12 de mayo de 2026

8 min de lectura

Arquitectura hexagonal sin ceremonias

Cómo separar UI, casos de uso e infraestructura en una app web sin convertir cada cambio en una capa extra.

Read in English

El problema no es la arquitectura, es dónde vive la decisión

Muchas aplicaciones web se vuelven difíciles de mantener no porque les falte una arquitectura famosa, sino porque la lógica importante termina distribuida entre controladores, componentes, hooks, ORMs y utilidades sueltas. Cuando eso pasa, el sistema compila, pero deja de ser claro.

La versión útil de la arquitectura hexagonal no consiste en dibujar seis carpetas y crear interfaces para todo. Consiste en hacer explícito qué parte del sistema toma decisiones de negocio, qué parte habla con el mundo externo y cómo se conectan ambas sin contaminarse entre sí.

El centro del sistema: casos de uso y puertos

En una app web pragmática, el centro suele ser un conjunto pequeño de casos de uso: crear un workspace, invitar a un usuario, publicar un artículo, recalcular un reporte. Cada caso de uso recibe datos de entrada, aplica reglas del dominio y delega efectos externos a través de puertos.

Un puerto no tiene que existir por dogma. Tiene sentido cuando protege una frontera real: persistencia, correo, jobs, pagos, caché, búsqueda, storage. Si mañana cambias Postgres por otro proveedor, o si necesitas testear sin red, el puerto ya está haciendo trabajo útil.

Un caso de uso pequeño, con dependencias explícitas.

type PublishArticleInput = {
  articleId: string;
  publishedAt: Date;
};

interface ArticleRepository {
  findDraftById(id: string): Promise<Article | null>;
  save(article: Article): Promise<void>;
}

export async function publishArticle(
  input: PublishArticleInput,
  deps: { articles: ArticleRepository },
) {
  const article = await deps.articles.findDraftById(input.articleId);

  if (!article) throw new Error('Draft not found');

  article.publish(input.publishedAt);
  await deps.articles.save(article);
}

Adaptadores delgados, no frameworks gobernando el dominio

Los adaptadores deberían ser aburridos. Un route handler convierte HTTP en input para un caso de uso. Un repositorio traduce entre el modelo persistido y el modelo del dominio. Un componente de UI presenta estado y dispara acciones. Si un adapter contiene decisiones de negocio, el borde del sistema ya tomó el control.

Esta separación también ayuda en frontend. Un formulario no debería decidir qué transición de estado es válida para una orden o una suscripción; debería enviar intención, recibir resultado y renderizar feedback. El dominio sigue siendo dominio aunque la app corra en el navegador.

  • Los casos de uso conocen reglas y secuencia.
  • Los adaptadores conocen protocolos y formatos.
  • La infraestructura conoce proveedores, SDKs y detalles operativos.

Cuándo sí y cuándo no

No hace falta montar hexagonal completo para una landing con un formulario y dos tablas. Pero cuando el producto ya tiene flujos importantes, side effects, permisos y reglas que cambian con frecuencia, separar decisiones del framework deja de ser purismo y se vuelve una mejora de velocidad.

La señal correcta no es el tamaño del repo. Es cuántas veces el equipo tiene que tocar cinco lugares distintos para cambiar una sola regla. Si eso ya está pasando, la arquitectura hexagonal deja de ser una aspiración y empieza a ser una herramienta.

Más artículos

Volver a artículos