Language:

Search

Introducción a la Arquitectura Hexagonal con Laravel

  • Share this:
Introducción a la Arquitectura Hexagonal con Laravel

¿Qué es la Arquitectura Hexagonal?

La arquitectura hexagonal, también conocida como Ports and Adapters, fue propuesta por Alistair Cockburn como una forma de estructurar aplicaciones para que sean independientes de frameworks, bases de datos, y otros detalles de infraestructura.

El objetivo es claro: aislar el dominio de negocio de los detalles técnicos. Así, tu lógica de negocio no dependerá de Laravel, ni de una base de datos, ni de ninguna herramienta externa.

Esto permite:

  • Hacer pruebas más fáciles y rápidas
  • Cambiar herramientas (base de datos, framework, servicios externos) sin tocar el núcleo del sistema
  • Reutilizar el dominio en diferentes contextos (web, CLI, API, etc.)

¿Cómo se ve esto en Laravel?

Laravel, por defecto, promueve una estructura basada en capas (Controllers, Models, Views, etc.). Pero no nos obliga a una arquitectura en particular.

La arquitectura hexagonal propone dividir el sistema en tres áreas principales:

1. Core (Dominio)

  • Entidades
  • Reglas de negocio
  • Casos de uso
  • Interfaces de puertos

2. Puertos (Ports)

  • Interfaces para entrada (por ejemplo, controladores)
  • Interfaces para salida (por ejemplo, repositorios, servicios externos)

3. Adaptadores (Adapters)

  • Implementaciones concretas para interactuar con Laravel, la base de datos, o APIs externas.

Estructura de Carpetas

Aquí un ejemplo realista en Laravel:

src/
├── Domain/
│   ├── User/
│   │   ├── Entities/
│   │   ├── ValueObjects/
│   │   ├── Repositories/
│   │   └── Services/
│
├── Application/
│   ├── User/
│   │   ├── UseCases/
│   │   └── DTOs/
│
├── Infrastructure/
│   ├── Persistence/
│   │   └── Eloquent/
│   ├── Http/
│   │   ├── Controllers/
│   │   └── Requests/
│   └── Providers/
│
└── Support/

Laravel seguiría manejando rutas, providers, y el ciclo de vida HTTP, pero la lógica de negocio está aislada en el Dominio y la Aplicación.


Ejemplo Rápido: Crear un Usuario

Supongamos que quieres crear un usuario. En una arquitectura tradicional de Laravel, harías todo en un Controller o Service. En hexagonal, se ve así:

Dominio

// Domain/User/Entities/User.php
class User
{
    public function __construct(
        public string $name,
        public string $email,
        public string $password
    ) {}
}
// Domain/User/Repositories/UserRepositoryInterface.php
interface UserRepositoryInterface
{
    public function save(User $user): void;
}

Caso de Uso

// Application/User/UseCases/CreateUserUseCase.php
class CreateUserUseCase
{
    public function __construct(
        private UserRepositoryInterface $repository
    ) {}
    public function execute(CreateUserDTO $dto): void
    {
        $user = new User($dto->name, $dto->email, bcrypt($dto->password));
        $this->repository->save($user);
    }
}

Infraestructura

// Infrastructure/Persistence/Eloquent/EloquentUserRepository.php
class EloquentUserRepository implements UserRepositoryInterface
{
    public function save(User $user): void
    {
        UserModel::create([
            'name' => $user->name,
            'email' => $user->email,
            'password' => $user->password
        ]);
    }
}
// Infrastructure/Http/Controllers/UserController.php
class UserController extends Controller
{
    public function store(Request $request, CreateUserUseCase $useCase)
    {
        $dto = new CreateUserDTO(
            $request->name,
            $request->email,
            $request->password
        );
        $useCase->execute($dto);
        return response()->json(['message' => 'User created successfully']);
    }
}

¿Y las ventajas?

  • Puedes probar CreateUserUseCase sin Laravel.
  • Puedes cambiar EloquentUserRepository por una API externa o una base de datos diferente.
  • El dominio es claro, limpio y reusable.

Conclusión

La arquitectura hexagonal no es solo una moda. Es una forma de diseñar sistemas mantenibles, testeables y desacoplados.

Laravel, aunque es un framework de propósito general, se adapta perfectamente a este enfoque si separas bien responsabilidades.

En próximos artículos exploraremos:

  • Cómo organizar los DTOs, entidades y value objects
  • Cómo inyectar dependencias en Laravel con interfaces
  • Cómo testear los casos de uso sin framework

 

 

 

 

Tags:
Carlos Santiago

Carlos Santiago

Laravel Developer