MDA

Español     English

Model Domain Architecture Logo

Nota importante

Model Domain Architecture (MDA) es un enfoque arquitectónico pragmático y flexible, inspirado en principios de Domain-Driven Design y Arquitectura Limpia, pero adaptado a necesidades reales de proyectos Laravel.

Su objetivo es ser un punto de partida claro y práctico, no un marco rígido ni exhaustivo como DDD, Hexagonal o Clean Architecture.
MDA define una organización de capas y responsabilidades recomendada, pero no impide técnicamente acceder directamente a componentes internos (Finder, Query, Action, etc.).

El camino recomendado es siempre pasar por los Services, y solo en casos puntuales usar accesos directos, con juicio y responsabilidad. Esta base puede expandirse o ajustarse según las necesidades del proyecto.

Model Domain Architecture (MDA)

La Model Domain Architecture (MDA) es un enfoque arquitectónico pragmático, inspirado en principios de Domain-Driven Design (DDD) y Arquitectura Limpia, pero adaptado específicamente a proyectos Laravel donde la separación natural se da por modelos más que por dominios conceptuales complejos.

MDA organiza el proyecto alrededor de los modelos centrales del sistema (por ejemplo: User, Order, Product, etc.), manteniendo una estructura clara, escalable y fácil de navegar incluso en aplicaciones con múltiples bases de datos.


🎯 Objetivo

Proveer una arquitectura:


1. Filosofía general

En MDA cada modelo del sistema funciona como un “dominio acotado”. No un bounded context como en DDD, sino un área funcional delimitada por el propio modelo y su base de datos.

Cada modelo contiene:

Esto crea pequeñas islas de responsabilidad clara.


2. Estructura de carpetas

app/
  Actions/
    Order/
    User/
    Product/
  DTO/
    Order/
    User/
    Product/
  Finders/
    OrderFinder.php
    UserFinder.php
    ProductFinder.php
  Queries/
    Order/
    User/
    Product/
  Repositories/
    OrderRepository.php
    UserRepository.php
    ProductRepository.php
  Services/
    Interfaces/
      OrderServiceInterface.php
      ClientServiceInterface.php
    OrderService.php
    ClientService.php
  Models/
    Main/
      Order.php
      User.php
      Product.php
    Logistic/
      Delivery.php

Nota: Models se agrupan por base de datos cuando la aplicación utiliza múltiples conexiones. Esta es una excepción válida porque responde a necesidades de infraestructura, no de dominio.


3. Descripción de cada componente

3.1 Models

Eloquent Models divididos por base de datos.

Esto es una excepción dentro de la arquitectura porque el modelo refleja la estructura física.

Ventajas:


3.2 Finders

Clases con métodos de lecturas simples:

Todas las búsquedas simples que no requieren joins elaborados o lógica compleja.

Se agrupan por modelo, en un único archivo por modelo:

OrderFinder.php
UserFinder.php

🔀 Variaciones posibles en la organización de Finders

MDA propone, por defecto, agrupar todos los métodos de lectura simples de un modelo en un único archivo, por ejemplo:

Esto mantiene el árbol de directorios liviano y evita crear decenas de clases pequeñas.

Sin embargo, esta no es la única forma válida de organizar los Finders. Si tu equipo prefiere una estructura más granular —por ejemplo, una clase Finder por consulta:

FindUserById.php
FindUsersByRole.php
FindOrdersByCustomer.php

También es totalmente compatible con MDA.

La idea central es que:

Las consultas simples estén separadas del servicio y la lógica de negocio.

La organización interna sea coherente para tu proyecto.

El equipo pueda modificar o escalar la estructura sin fricción.

En otras palabras:

MDA define dónde viven las cosas, pero no cómo deben verse exactamente. Cada proyecto puede ajustar el nivel de granularidad que prefiera.


3.3 Queries

Consultas SQL/Eloquent complejas:

Se agrupan por carpetas de modelo, por ejemplo:

Queries/Order/OrderQueries.php
Queries/User/UserQueries.php

Los queries están aislados porque es normal que crezcan mucho.


3.4 Repositories

Clases enfocadas en persistencia básica:

Evitan la sobrecarga de tener 50 métodos especializados dentro del repositorio.

Las consultas complejas NO se mezclan aquí; van en Queries.

Las búsquedas simples NO se mezclan aquí; van en Finders.


3.5 Actions

Las Actions representan un caso de uso completo.

Las Actions no deben contener lógica de negocio propia del dominio, sino coordinar la ejecución de piezas específicas.


3.6 DTOs

Objetos para transportar datos, ordenar requests y respuestas.

Separados por modelo.


3.7 Services

Los Services encapsulan la lógica específica de un modelo o una operación reutilizable.

Un Service puede:

Los Services no deben decidir flujos de alto nivel ni contener lógica de casos de uso compuestos. Eso es responsabilidad de las Actions o Servicios Compuestos.


3.8 Servicios Compuestos

Además de los servicios que están directamente asociados a un modelo específico, en MDA también se contemplan los Servicios Compuestos.

Un Servicio Compuesto corresponde a un caso de uso del sistema que:

Ejemplos típicos de Servicios Compuestos pueden ser:

Los Servicios Compuestos suelen ser orquestadores de múltiples Services y/o Actions. En la práctica, estos casos se expresan como Actions de alto nivel que encapsulan el flujo completo del caso de uso transversal.

📌 ¿Dónde se ubican?

A diferencia de los modelos (como Order, User, etc.), los Servicios Compuestos no tienen un modelo físico asociado.
Sin embargo, para mantener la consistencia de Model Domain Architecture, estos servicios:

Por ejemplo:

app/
├── Services/
│ ├── Order/
│ ├── User/
│ └── Notification/ ← Servicio Compuesto
│   └── NotificationService.php
├── DTO/
│ ├── Order/
│ ├── User/
│ └── Notification/ ← DTO específico
│   └── NotificationDTO.php
├── Actions/
│ ├── Order/
│ ├── User/
│ └── Notification/ ← Acciones
│   ├── EjecutarNotification.php
│   └── ValidarNotification.php
├── Queries/
│ ├── Order/
│ ├── User/
│ └── Notification/ ← Consultas propias

🧾 ¿Por qué es consistente con MDA?

Aunque un Servicio Compuesto no tiene un modelo Eloquent asociado, sigue:

Los Servicios Compuestos son conceptualmente similares a lo que en otras arquitecturas se conoce como:

Integrar este tipo de servicios de forma explícita en MDA permite mantener la estructura uniforme, predecible y escalable sin forzar que todo dependa de un único modelo.


4. Relación entre componentes

Flujo recomendado:

Controller → Action → Services → (Finder / Query / Repository)

Donde:

Relaciones específicas:

Las dependencias son unidireccionales, claras y limpias.


5. Ventajas de MDA

✓ Escalabilidad natural

A medida que crece el proyecto, solo crecen carpetas dentro del modelo correspondiente.

✓ Navegación inmediata

Todo lo relacionado a Order está en un mismo “dominio de modelo”.

✓ Sin super-repositorios gigantes

Las consultas específicas no se mezclan con las CRUD básicas.

✓ Alineado a la realidad de muchos proyectos Laravel

Muchos proyectos no tienen dominios de negocio bien definidos para aplicar DDD completo.

✓ Compatible con DDD parcial

Si algún día aparece un dominio grande (por ejemplo, “Finanzas”), puede agrupar varios modelos bajo un contexto.


6. Ejemplo resumido de flujo

Controller de Ordenes:

$order = $orderService->findById($id);

Service:

return $this->finder->findById($id);

Consulta compleja:

$orders = $orderService->getOrdenesConDescuento();

Service llama:

Actualización:

$orderService->actualizarEstado($id, $dto);

Service → Action → Repository


7. Cuándo usar MDA

Ideal para proyectos:

No tan ideal en:


8 Como usar MDA (Recomendaciones y buenas prácticas)

MDA define una estructura clara y responsabilidades bien delimitadas, pero no impone restricciones técnicas rígidas. No es una arquitectura que “te impide” hacer cosas, sino una que te sugiere caminos preferidos.

Esta sección describe cómo se espera usar MDA en la práctica, y qué decisiones son recomendadas… aunque no obligatorias.


8.1 El camino recomendado

La idea general es:

Controller → Action → Services → (Finder / Query / Repository)

Los Controllers no contienen lógica de negocio. Delegan la ejecución a una Action.

Las Actions representan casos de uso:

Desde una Action se puede:

Este flujo mantiene:


8.2 Reglas básicas no estrictas

MDA no bloquea técnicamente otros accesos.

Por ejemplo:

👉 Nada lo impide.

La diferencia clave es la intención.

Recomendación:

MDA prioriza claridad antes que enforcement técnico.


8.3 Ubicacion de la lógica de negocio

La lógica de negocio debería vivir fuera de controllers

Preferentemente dentro de:

MDA no fuerza el uso de:

Pero no los prohíbe.

Si un proyecto crece y necesita conceptos más avanzados, MDA puede:


8.4 Pragmatismo sobre purismo

MDA nace desde la práctica, no desde la teoría.

Si una regla:

Romperla conscientemente es preferible a seguirla a ciegas.

La clave es:


8.5 MDA es un punto de partida

MDA no intenta:

Su objetivo es:

Si en algún punto necesitás más, probablemente:

ya sabés mejor que MDA qué es lo que hace falta.


9. Conclusión

La Model Domain Architecture (MDA) ofrece un balance perfecto entre organización, escalabilidad y simplicidad. Su premisa fundamental es que los modelos son el eje central del diseño, y todo lo relacionado a un modelo vive junto a él.

Es una arquitectura práctica, realista y altamente usable en equipos que trabajan con Laravel, especialmente con múltiples bases de datos y dominios que no encajan perfectamente en DDD tradicional.