03 · Puertos y Adaptadores

Objetivo: profundizar en la clasificación de puertos y adaptadores, su organización en Node.js y buenas prácticas para garantizar un acoplamiento mínimo y máxima testabilidad.

Nota de contexto:

  • Un Puerto es una interfaz dentro de la capa de aplicación que define un contrato: qué hace el sistema, sin detallar cómo.

  • Un Adaptador es la implementación concreta de ese contrato, en la capa de infraestructura: cómo interactúa con una base de datos, un broker de mensajes o un framework HTTP.

1. Taxonomía de puertos y adaptadores

Tipo
Alias
Definido en
Ejemplos

Puerto de Entrada

Driving / Primary

Capa de aplicación

RegisterUserCommand, GetOrderQuery

Puerto de Salida

Driven / Secondary

Capa de aplicación

UserRepositoryPort, PaymentGatewayPort

Adaptador de Entrada

Controller / Handler

Infraestructura (HTTP, CLI)

FastifyHandler, GraphQLResolver, CLIParser

Adaptador de Salida

Gateway

Infraestructura (DB, MQ, API)

PostgresUserRepository, StripePaymentGateway

2. Diagrama conceptual (Mermaid)

spinner

3. Ejemplo de puerto de salida: PaymentGatewayPort

3.1. Definición del puerto

// src/domain/ports/PaymentGatewayPort.ts
/**
 * Puerto de salida: define el contrato para procesar pagos.
 * La capa de dominio solo conoce esta interfaz.
 */
export interface PaymentGatewayPort {
  charge(amount: number, currency: string): Promise<{ receiptId: string }>;
}

3.2. Implementación concreta del puerto

4. Adaptador de entrada: HTTP Handler

5. Inversión de Dependencias (DIP) en main.ts

6. Anti-patrones comunes

Anti-patrón
Riesgo
Solución recomendada

Fat Adapter

Mezcla lógica de negocio en controllers. Ver Punto 4.

Extraer lógica a UseCases / Domain Services

Domain (Head Up Display) HUD

Logging/tracing directo en entidades

Inyectar un LoggerPort en adaptadores

Anonymous Interface

Usar any para puertos, perdiendo tipado

Definir interfaces específicas y pequeñas

7. Buenas prácticas

  1. Puertos “skinny”: interfaces de 1–3 métodos con responsabilidad clara.

  2. Adaptadores “thin”: realizan validación y mapeo de DTOs ↔ entidades; toda la lógica de negocio permanece en el dominio o en Use Cases.

  3. Use Cases orquestan: coordinan puertos, adaptadores y emisión de eventos, evitando lógica dispersa.

  4. Tests unitarios de adapters: verificar que un adapter cumple el contrato en memoria sin necesidad de servicios externos.

Ejemplo de test unitario para un adapter de salida

Última actualización