[ SYSTEM ] / LOGBOOK / arquitectura-hexagonal-frontend

Arquitectura Hexagonal en el Frontend: Escalabilidad y Desacoplamiento

Aprende a implementar Arquitectura Hexagonal (Ports & Adapters) en React y Astro. Desacopla la lógica de negocio de la UI para crear aplicaciones web escalables.

DATE: 20/11/2025
Arquitectura Hexagonal en el Frontend: Escalabilidad y Desacoplamiento

El ecosistema Frontend es caótico por naturaleza. Los frameworks cambian, las librerías de estado quedan obsoletas, y las APIs de backend evolucionan. Si tu lógica de negocio está fuertemente acoplada a tus componentes de React o Astro, tu deuda técnica crecerá exponencialmente.

La Arquitectura Hexagonal (o Ports and Adapters), conceptualizada por Alistair Cockburn, ha sido un pilar en el backend durante décadas. Hoy, aplicarla en el cliente (Frontend) no es una extravagancia; es un requisito para aplicaciones de grado empresarial.

¿Por qué el Frontend necesita desacoplarse?

Imagina que estás construyendo un e-commerce complejo. El flujo típico del developer es escribir un useEffect que llama a fetch y actualiza el estado local del componente usando useState.

// ❌ Anti-patrón: Lógica de infraestructura acoplada a la UI
function ProductList() {
  const [products, setProducts] = useState([]);
  
  useEffect(() => {
    fetch('/api/v1/products')
      .then(res => res.json())
      .then(data => setProducts(data));
  }, []);

  return <div>{/* Render logic */}</div>;
}

¿Qué pasa si cambias tu API a GraphQL? ¿Qué pasa si necesitas mockear los datos para tests unitarios? Tienes que reescribir los componentes de UI.

Puertos y Adaptadores en el Cliente

En una arquitectura hexagonal, el sistema se divide en tres capas principales:

  1. Dominio (Domain): Entidades, reglas de negocio. Es puro TypeScript, sin dependencias de React ni del navegador.
  2. Aplicación (Application / Casos de Uso): Orquesta el flujo de datos. Define interfaces (Puertos).
  3. Infraestructura (Infrastructure): La capa externa. Contiene la UI (React/Astro) y los Adaptadores (Axios, Fetch, LocalStorage).

El Flujo de Inversión de Dependencias

Para lograr este desacoplamiento, utilizamos el Principio de Inversión de Dependencias (la ‘D’ en SOLID).

// 1. Definimos el Puerto (Domain/Application)
export interface ProductRepository {
  getProducts(): Promise<Product[]>;
  getProductById(id: string): Promise<Product>;
}

// 2. Implementamos el Adaptador (Infrastructure)
export class ApiProductRepository implements ProductRepository {
  async getProducts(): Promise<Product[]> {
    const res = await fetch('https://api.empresa.com/products');
    return res.json();
  }
}

Inyectando Dependencias en React

En lugar de que nuestro componente sepa cómo conseguir los datos, simplemente le inyectamos el caso de uso o el repositorio.

// ✅ Componente Desacoplado
interface Props {
  repository: ProductRepository;
}

export function ProductList({ repository }: Props) {
  const [products, setProducts] = useState<Product[]>([]);

  useEffect(() => {
    repository.getProducts().then(setProducts);
  }, [repository]);

  return (
    <ul>
      {products.map(p => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}

Beneficios de este Enfoque

  1. Testabilidad Absoluta: Puedes crear un MockProductRepository que devuelva datos estáticos. Tus tests de UI correrán en milisegundos sin necesidad de interceptar llamadas de red.
  2. Migración Zero-Friction: ¿Pasas de React a Vue? El dominio y los adaptadores de red se mantienen intactos.
  3. Desarrollo Paralelo: El equipo de Frontend puede trabajar con adaptadores falsos (In-Memory) mientras el equipo de Backend termina la API real.

Conclusión

La Arquitectura Hexagonal exige una inversión inicial de tiempo y código (boilerplate). No la utilices para landing pages o proyectos sencillos. Sin embargo, si estás construyendo un SaaS complejo, un panel B2B o una plataforma Fintech de alto rendimiento, este modelo de separación te garantizará una escalabilidad técnica sin precedentes.