Cómo Aplicar DDD en Laravel y Diseñar Software Profesional Basado en Dominios
Aplicar Domain Driven Design en Laravel puede parecer un reto si solo has trabajado con el enfoque tradicional MVC. Sin embargo, adoptar una arquitectura centrada en el dominio puede ayudarte a crear software profesional, escalable y mantenible desde el primer commit.
En este artículo, te explico cómo transformar tu enfoque de desarrollo y adoptar DDD en Laravel, con ejemplos prácticos, estructuras de carpetas reales y mucho código explicativo. Ideal si quieres llevar tu desarrollo con Laravel al siguiente nivel.
Únete a nuestra comunidad de DiscordÍndice
Qué Es Domain Driven Design y Por Qué Aplicarlo en Laravel
Antes de sumergirnos en código, es vital entender qué es el DDD (Domain Driven Design) y cuándo tiene sentido implementarlo. Este enfoque propone estructurar el software centrándose en el conocimiento del dominio y en cómo interactúa con el negocio.
Principios clave del diseño basado en dominio
Domain Driven Design se basa en:
-
- Modelo de Dominio: una representación del conocimiento y lógica del negocio.
-
- Lenguaje Ubicuo: un lenguaje compartido entre desarrolladores y expertos del dominio.
-
- Separación de responsabilidades: cada capa tiene una función clara (dominio, aplicación, infraestructura).
"El diseño basado en dominio no es solo una técnica de programación, sino una forma de pensar." – Eric Evans
Cómo se integra el Domain Driven Design en Laravel
Laravel es un framework muy flexible. Aunque por defecto propone un enfoque MVC, permite adaptar perfectamente una arquitectura basada en dominios. Puedes comenzar poco a poco, organizando tus entidades y servicios en capas, y delegando responsabilidades a servicios de aplicación e infraestructura.
Beneficios reales del DDD para desarrolladores Laravel
| Ventaja | Explicación |
|---|---|
| ✨ Mantenibilidad | Los cambios en reglas de negocio no rompen otras partes del sistema |
| 🌍 Escalabilidad | Permite que el software crezca sin ser una bola de nieve de código |
| ⚖️ Legibilidad | Facilita que nuevos desarrolladores entiendan el flujo del sistema |
| 🤝 Colaboración | El lenguaje ubicuo mejora la comunicación con el equipo de negocio |
Arquitectura Limpia en Laravel Basada en DDD
Uno de los grandes beneficios del DDD es que permite adoptar una arquitectura limpia. Esto se traduce en separar bien las responsabilidades y evitar que el framework gobierne tu aplicación.
Laravel arquitectura limpia vs arquitectura tradicional
Veamos un ejemplo de estructura tradicional (MVC):
app/
Http/
Controllers/
Models/
Views/
En cambio, con DDD la estructura podría ser:
src/
Domain/
User/
User.php
UserRepository.php
Application/
User/
CreateUserService.php
Infrastructure/
Persistence/
EloquentUserRepository.php
Interfaces/
Http/
Controllers/
CreateUserController.php
Esto separa claramente las capas: Dominio, Aplicación, Infraestructura y Interfaces.
Aplicar patrones de arquitectura en proyectos Laravel
-
- Entities y Value Objects viven en el Dominio.
-
- Casos de Uso en Aplicación (services).
-
- Adapters como repositorios y providers en Infraestructura.
// Dominio: User.php
class User {
public function __construct(
public readonly string $name,
public readonly Email $email,
) {}
}
// Aplicación: CreateUserService.php
class CreateUserService {
public function __construct(private UserRepository $repo) {}
public function execute(string $name, string $email) {
$user = new User($name, new Email($email));
$this->repo->save($user);
}
}
Ejemplos prácticos de estructura DDD en Laravel
Puedes organizar tus proyectos en /src para separar el dominio del framework Laravel.
Tip: configura el composer.json con:
"autoload": {
"psr-4": {
"App\\": "app/",
"Src\\": "src/"
}
}
Cómo empezar un proyecto DDD en Laravel
Vamos a ver paso a paso cómo transformar un proyecto Laravel tradicional en uno con enfoque DDD. Aquí tienes una estructura mínima inicial:
laravel new mi-proyecto-ddd
cd mi-proyecto-ddd
mkdir -p src/User/{Domain,Application,Infrastructure,Http,Database}
1. Capa de Dominio
Aquí va el core de tu lógica: entidades, objetos de valor, agregados e interfaces.
src/User/Domain/User.php
namespace Src\User\Domain;
class User
{
public function __construct(
public readonly int $id,
public string $name,
public string $email
) {}
}
2. Capa de Aplicación
Esta capa orquesta la lógica y casos de uso.
src/User/Application/RegisterUser.php
namespace Src\User\Application;
use Src\User\Domain\UserRepository;
use Src\User\Domain\User;
class RegisterUser
{
public function __construct(private UserRepository $repository) {}
public function handle(string $name, string $email): void
{
$user = new User(null, $name, $email);
$this->repository->save($user);
}
}
3. Capa de Infraestructura
Aquí implementamos los contratos definidos en el dominio.
src/User/Infrastructure/EloquentUserRepository.php
namespace Src\User\Infrastructure;
use App\Models\User as EloquentUser;
use Src\User\Domain\User;
use Src\User\Domain\UserRepository;
class EloquentUserRepository implements UserRepository
{
public function save(User $user): void
{
EloquentUser::create([
'name' => $user->name,
'email' => $user->email
]);
}
}
4. Capa HTTP
Aquí conectamos las rutas con la capa de aplicación.
src/User/Http/RegisterController.php
namespace Src\User\Http;
use Illuminate\Http\Request;
use Src\User\Application\RegisterUser;
class RegisterController
{
public function __invoke(Request $request, RegisterUser $action)
{
$action->handle($request->name, $request->email);
return response()->json(['message' => 'Usuario registrado']);
}
}
Y en tus rutas:
Route::post('/register', \Src\User\Http\RegisterController::class);
Separación de capas: dominio, aplicación e infraestructura
-
- Dominio: entidades, repositorios, reglas del negocio
-
- Aplicación: servicios, casos de uso, DTOs
-
- Infraestructura: implementaciones concretas, adaptadores
-
- Interfaces: controladores, comandos, listeners
Cómo hacer pruebas unitarias y funcionales en una arquitectura DDD
-
- Dominio: sin dependencia de Laravel, fácil de testear
-
- Aplicación: mockea los repositorios
public function test_create_user_service() {
$repo = Mockery::mock(UserRepository::class);
$repo->shouldReceive('save')->once();
$service = new CreateUserService($repo);
$service->execute('Pepe', '[email protected]');
$this->assertTrue(true);
}
Consejos Finales Para un Desarrollo Limpio y Profesional en Laravel
Implementar DDD en Laravel no es para todos los proyectos. Tiene sentido cuando:
-
- El proyecto crecerá en funcionalidades y complejidad
-
- Necesitas separar lógica de negocio del framework
-
- Trabajas en equipo y necesitas colaborar con otros roles
Laravel avanzado con DDD y técnicas modernas
Aplica principios de SOLID, hexagonal architecture, CQRS, y mantén tu dominio libre de dependencias.
Buenas prácticas y errores comunes al organizar código Laravel
Evita:
-
- Repetir lógica de negocio en los controladores
-
- Inyectar modelos de Eloquent en el dominio
-
- Hacer que la infraestructura tome decisiones del negocio
Haz esto:
-
- Prueba tus servicios de aplicación sin necesidad de Laravel
-
- Usa interfaces para desacoplar lógicas
-
- Trabaja con entidades puras sin dependencia de Eloquent
Herramientas recomendadas para proyectos con DDD Laravel
-
- PHPStan y Psalm para tipos estáticos
-
- PHPUnit para testing
-
- Laravel IDE Helper para autocompletado
-
- Docker para aislar entorno
Cómo escalar tu código siguiendo buenas prácticas Laravel
-
- Usa un sistema de carpetas claro desde el inicio
-
- Documenta tu lenguaje ubicuo
-
- Usa eventos para comunicar capas
-
- Separa los módulos del dominio por contexto
Conclusión
Adoptar Domain Driven Design en Laravel puede transformar tu forma de construir software. Aunque al principio suponga un cambio de mentalidad, los beneficios en claridad, escalabilidad y mantenimiento son enormes.
Recuerda que no necesitas aplicar todo de golpe. Puedes comenzar poco a poco, modularizando tu dominio y extrayendo la lógica de tus controladores. Tu futuro "yo" (y tu equipo) te lo agradecerá.
Preguntas Frecuentes
No. Solo en aquellos con suficiente complejidad y reglas de negocio. Para un CRUD simple, el MVC tradicional es suficiente.
Totalmente. Laravel es muy flexible y puedes usar DDD sin problemas.
Sí, pero es recomendable ir paso a paso, entendiendo bien cada capa y su propósito.