Language:

Search

Dominio: Entidades, Reglas y Repositorios

  • Share this:
Dominio: Entidades, Reglas y Repositorios

Dominio: Entidades, Reglas y Repositorios

En los dos artículos anteriores vimos qué es la arquitectura hexagonal y cómo estructurar un proyecto Laravel para aplicarla.
Hoy vamos a entrar en el corazón de todo esto: el Dominio.

Y cuando digo “corazón” no es solo por decir algo bonito. El dominio es literalmente la razón de ser de tu aplicación. Es donde vive la lógica de negocio, esas reglas que no dependen de Laravel, ni de MySQL, ni de ninguna moda pasajera en el desarrollo.


El Dominio: tu negocio en código

Piensa que mañana decides cambiar Laravel por Symfony, o incluso por un microframework. O que en lugar de MySQL usas MongoDB. El dominio debería seguir funcionando exactamente igual, porque no debería depender de nada externo.

En el dominio viven:

  • Entidades → Representan objetos del mundo real o del negocio.
  • Objetos de valor (Value Objects) → Tipos pequeños con reglas propias.
  • Servicios de dominio → Lógica que no pertenece a una sola entidad.
  • Interfaces de repositorio → Contratos para guardar y recuperar datos.

Entidades: más que simples modelos

En Laravel solemos llamar “modelo” a lo que realmente es un Active Record.
En arquitectura hexagonal, una entidad es solo una clase PHP que representa algo importante para el negocio.

Ejemplo básico:


// src/Domain/User/Entities/User.php

namespace Src\Domain\User\Entities;

use Src\Domain\User\ValueObjects\Email;

class User
{
    public function __construct(
        private string $name,
        private Email $email
    ) {}

    public function changeEmail(Email $newEmail): void
    {
        // Aquí podrías validar reglas de negocio antes de cambiarlo
        $this->email = $newEmail;
    }

    public function name(): string
    {
        return $this->name;
    }

    public function email(): Email
    {
        return $this->email;
    }
}


No hay Eloquent, ni base de datos, ni nada que huela a Laravel. Solo PHP puro.


Value Objects: reglas encapsuladas

Un Value Object no es más que una clase pequeña que representa un concepto con valor y comportamiento propio.

Por ejemplo, un email:

// src/Domain/User/ValueObjects/Email.php

namespace Src\Domain\User\ValueObjects;

class Email
{
    public function __construct(private string $value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException("Email inválido");
        }
    }

    public function value(): string
    {
        return $this->value;
    }
}

 

Esto garantiza que si un objeto Email existe en tu aplicación, es válido. Te ahorras validaciones repetidas en todos lados.


Repositorios: contratos, no implementaciones

Un repositorio en el dominio es solo una interfaz.
No dice cómo guardar datos, solo qué métodos hay que tener para trabajar con ellos.

// src/Domain/User/Repositories/UserRepositoryInterface.php

namespace Src\Domain\User\Repositories;

use Src\Domain\User\Entities\User;

interface UserRepositoryInterface
{
    public function save(User $user): void;

    public function findById(int $id): ?User;
}

 

En esta capa no nos importa si usas MySQL, Redis, o guardas los datos en una libreta de papel. Eso lo veremos en la capa de infraestructura.


Lo que NO debe haber en el dominio

  • SQL → ni una sola query.
  • Eloquent Models
  • Facades o helpers de Laravel
  • Lógica de presentación (HTML, Blade, JSON)

Dependencias externas (Guzzle, Carbon, etc. — solo si son imprescindibles)

El dominio debe ser lo más puro posible.
Cuanto más limpio lo mantengas, más fácil será testearlo y más independiente será de cualquier framework.


Testeando el dominio

Aquí está la magia:
Puedes probar tus entidades, value objects y servicios sin levantar Laravel.
Con PHPUnit puro, sin base de datos, sin mocks complicados.

Por ejemplo:

public function test_can_change_email()
{
    $user = new User("Carlos", new Email("carlos@example.com"));
    $user->changeEmail(new Email("nuevo@example.com"));

    $this->assertEquals("nuevo@example.com", $user->email()->value());
}


Este test no necesita saber nada del resto de la aplicación.


Consejos prácticos

  1. Piensa en términos de negocio, no de base de datos.
    Si tu cliente dice “Usuario” y “Reserva”, esos son tus agregados y entidades.
  2. Aplica inmutabilidad en Value Objects siempre que puedas.
    Son más seguros y fáciles de razonar.
  3. Haz cumplir las reglas en el constructor de tus objetos.
    Así nunca existirá un estado inválido.
  4. No abuses de los servicios de dominio.
    Si algo pertenece a una entidad, ponlo ahí.

Conclusión

El dominio es donde debes invertir más cuidado y cariño. Aquí es donde tu aplicación dice “quién es” y “qué hace”.
Si el dominio está limpio y bien modelado, el resto de la arquitectura se construye sobre bases sólidas.

En el próximo artículo veremos cómo implementar la capa de aplicación: casos de uso y cómo orquestar la lógica del dominio sin acoplarla a Laravel.

 

Carlos Santiago

Carlos Santiago

Laravel Developer