Language:

Search

Casos de Uso y Servicios de Aplicación

  • Share this:
Casos de Uso y Servicios de Aplicación

En el artículo anterior nos metimos de lleno en el Dominio:

  • Modelamos entidades y objetos de valor
  • Definimos interfaces de repositorio
  • Establecimos las reglas de negocio fuera del framework

Ahora vamos a la siguiente capa en nuestra arquitectura hexagonal: la capa de aplicación.

Esta es la parte que orquesta la lógica del dominio para resolver acciones concretas que el sistema debe realizar.
Es la capa que entiende qué queremos hacer, pero no necesariamente cómo se hace a nivel de infraestructura.


Una analogía rápida

Imagina que tu dominio es un conjunto de herramientas (entidades, value objects, servicios de dominio).
Los casos de uso serían el “manual de instrucciones” que explica cómo usar esas herramientas para conseguir un objetivo.

Por ejemplo:

  • Registrar un usuario
  • Procesar un pedido
  • Enviar un correo de bienvenida
  • Cancelar una reserva

Cada una de esas acciones es un caso de uso.


¿Qué es un Caso de Uso?

Un caso de uso es una clase que:

  1. Recibe una solicitud (normalmente un DTO o parámetros)
  2. Orquesta la lógica del dominio
  3. Llama a repositorios para persistir o recuperar datos
  4. Devuelve un resultado o no devuelve nada

Importante:
Un caso de uso no tiene lógica de presentación (HTML, JSON, etc.) y no depende del framework.
Es puro PHP que podrías ejecutar desde un controlador, una CLI, un job, o incluso un test unitario.


Ejemplo: Registrar un Usuario

Supongamos que en nuestro dominio tenemos:

  • User (entidad)
  • UserRepositoryInterface (repositorio)
  • Email (value object)

Nuestro caso de uso podría verse así:

// src/Application/User/UseCases/RegisterUserUseCase.php

namespace Src\Application\User\UseCases;

use Src\Domain\User\Entities\User;
use Src\Domain\User\Repositories\UserRepositoryInterface;
use Src\Domain\User\ValueObjects\Email;
use Src\Application\User\DTOs\RegisterUserDTO;

class RegisterUserUseCase
{
    public function __construct(
        private UserRepositoryInterface $repository
    ) {}

    public function execute(RegisterUserDTO $dto): void
    {
        $user = new User($dto->name, new Email($dto->email));

        $this->repository->save($user);
    }
}


Fíjate que aquí no hay Eloquent, ni requests de Laravel, ni validaciones de Form Request.
Eso vive fuera, en la infraestructura.


DTOs: Datos bien empaquetados

Los Data Transfer Objects (DTOs) son simplemente clases que agrupan y tipan los datos que necesita un caso de uso.

// src/Application/User/DTOs/RegisterUserDTO.php

namespace Src\Application\User\DTOs;

class RegisterUserDTO
{
    public function __construct(
        public string $name,
        public string $email
    ) {}
}


Esto evita pasar un montón de parámetros sueltos y mantiene el contrato del caso de uso claro y estable.


Servicios de Aplicación

A veces hay procesos que no son casos de uso concretos, pero que sirven de apoyo a varios de ellos.

Por ejemplo:

  • Un servicio que calcule descuentos
  • Un servicio que envíe notificaciones
  • Un servicio que maneje conversiones de moneda

Estos servicios de aplicación:

  • Pueden usar repositorios
  • Pueden llamar a otros casos de uso
  • Siguen sin depender de Laravel

Ejemplo:

// src/Application/Shared/Services/DiscountCalculator.php

namespace Src\Application\Shared\Services;

class DiscountCalculator
{
    public function calculate(float $price, int $percentage): float
    {
        return $price - ($price * $percentage / 100);
    }
}

 


Errores comunes

  1. Meter lógica de dominio en el caso de uso
    → El caso de uso orquesta, no valida ni crea reglas. Eso es trabajo del dominio.
  2. Acoplar el caso de uso a Laravel
    → Evita inyectar Request de Laravel o Eloquent Models aquí.
  3. No usar DTOs
    → Terminas con métodos que tienen demasiados parámetros y son difíciles de mantener.
  4. Hacer casos de uso genéricos
    → Un caso de uso debe tener un propósito claro y único.

Probando casos de uso

La belleza de esta capa es que puedes testear un caso de uso sin cargar Laravel:

public function test_can_register_a_user()
{
    $repository = new InMemoryUserRepository(); // implementación de prueba

    $useCase = new RegisterUserUseCase($repository);

    $dto = new RegisterUserDTO("Carlos", "carlos@example.com");

    $useCase->execute($dto);

    $this->assertCount(1, $repository->all());
}


Esto hace que tus tests sean rápidos y confiables.


Consejos para esta capa

  • Un caso de uso = una acción concreta.
  • Nombres claros: CreateOrderUseCase, CancelBookingUseCase.
  • Inyecta solo las dependencias necesarias.
  • Mantén esta capa ligera, sin lógica compleja.
  • No abuses de los servicios de aplicación: si algo solo se usa en un caso de uso, déjalo en ese caso de uso.

Conclusión

Los casos de uso y servicios de aplicación son el puente entre tu dominio y el mundo exterior.
Aquí defines cómo se logran los objetivos del negocio, pero sin ensuciarlo con detalles técnicos.

Si tu dominio es el “qué” de tu aplicación, la capa de aplicación es el “cómo se consigue”.

En el próximo artículo veremos los Adaptadores: cómo Laravel y otras tecnologías interactúan con nuestro núcleo sin romper la independencia del dominio.


 

Carlos Santiago

Carlos Santiago

Laravel Developer