El Domain layer de UMS (Ums.Domain) actualmente hereda de clases base AggregateRoot<T> y Entity<T> proporcionadas por BeyondNetCode.Shell.Ddd. Esto crea una dependencia transitiva haciaMediatR (v12.3.0) a través de la librería shell.
Ums.Domain (Proyecto)
└── ProjectReference → BeyondNetCode.Shell.Ddd
└── PackageReference → MediatR (12.3.0)
src/apps/ums.api/Ums.Domain/Authorization/Profile/Profile.cs):public sealed class Profile : AggregateRoot<Profile, ProfileProps>
{
// Hereda: Id, BrokenRules, IsValid(), DomainEvents
}
Clase Base del Shell (libs/shell/ddd/src/BeyondNetCode.Shell.Ddd/):
public abstract class AggregateRoot<T, TProps> : Entity<T, TProps>
where TProps : Props
{
public IDomainEvents DomainEvents { get; }
// ... Integración con MediatR
}
BeyondNetCode.Shell.Ddd.Opción B:Refactorizar a diseño basado en composición, removiendo herencia del shell.
Opción C:Crear un proyecto “Domain.Abstractions” con interfaces puras, removiendo MediatR del shell.
| # | Pro | Justificación | |—|—–|—————| | 1 | Velocidad de Desarrollo | Los equipos pueden enfocarse en lógica de negocio, no en infraestructura | | 2 | Patrones Consistentes | Todos los aggregates comparten comportamiento base idéntico | | 3 | MediatR como Infraestructura | MediatR está a nivel shell, no directamente en Domain | | 4 | Battle-Tested | Las shell libraries son compartidas entre múltiples proyectos | | 5 | Menos Código a Mantener | No se necesitan implementaciones duplicadas de AggregateRoot | #### Contras | # | Contra | Justificación | |—|——–|—————| | 1 | Violación de Pureza del Domain | Domain referencia NuGet externo transitivamente | | 2 | Riesgo de Filtración de Framework | Si el shell evoluciona, el Domain podría verse forzado a cambiar | | 3 | Complejidad en Testing | Los tests del Domain requieren resolución de ensamblados de MediatR | | 4 | Contaminación Conceptual | El concepto de “Aggregate” del Domain conoce a MediatR | | 5 | Pérdida de Portabilidad | El Domain no puede extraerse como paquete separado | —
| # | Pro | Justificación | |—|—–|—————| | 1 | Pureza Real del Domain | Domain tiene cero dependencias externas | | 2 | Extraíble | El Domain podría publicarse como NuGet independiente | | 3 | Testabilidad | Los POCOs puros son más fáciles de testear unitariamente | | 4 | Sin Acoplamiento Conceptual | El Domain no conoce a MediatR | #### Contras | # | Contra | Justificación | |—|——–|—————| | 1 | Refactorización Masiva | 100+ entities necesitan modificación | | 2 | Pérdida de Consistencia | Cada aggregate podría implementar patrones diferente | | 3 | Proliferación de Boilerplate | Comportamiento común duplicado entre aggregates | | 4 | Cambio Rupturista | Todos los bounded contexts afectados | | 5 | Inversión de Tiempo | Estimado 3-4 semanas de trabajo | —
Crear Ums.Domain.Abstractions con interfaces puras:
IAggregateRoot<T>IEntity<T, TProps>IDomainEventsShell.Ddd implementa estas interfaces. Domain referencia solo Abstractions.
| # | Pro | Justificación | |—|—–|—————| | 1 | Claridad Arquitectónica | Separación clara entre contratos e implementación | | 2 | Pureza del Domain | Domain solo depende de Abstractions (sin NuGets) | | 3 | Flexibilidad | Se puede cambiar implementación del shell si es necesario | | 4 | Mantenible | Cambios en MediatR no impactan al Domain | #### Contras | # | Contra | Justificación | |—|——–|—————| | 1 | Otra Capa | Añade indirección sin beneficio inmediato | | 2 | Riesgo de Over-Engineering | 3 proyectos donde 2 podrían bastar | | 3 | Esfuerzo de Migración | Requiere crear proyecto Abstractions y actualizar referencias | | 4 | Complejidad de Build | Más proyectos = tiempos de build más largos | —
Regla BMAD R-10establece: “Domain debe ser POCOs puros con cero referencias NuGet” - pero esta regla esaspiracionalen interpretación estricta. La naturaleza transitiva de las dependencias del shell es uncompromiso controlado.
Arquitectura Pragmática: La librería shell es unshared kernel (concepto DDD). MediatR no es una preocupación del Domain - es infraestructura para manejar comandos/queries. El Domain no invoca MediatR directamente; solo usa clases base que happen to include it.
Evaluación de Riesgos:
Path de migración:
Ums.Domain.AbstractionsIAggregateRoot<T>, IEntity<T>, IDomainEventsAggregateRoot<T> en shell implemente estas interfacesShell.Ddd a Shell.Ddd.AbstractionsPara verificar la severidad de la violación de pureza del Domain, ejecutar:
dotnet list src/apps/ums.api/Ums.Domain/Ums.Domain.csproj package
# Debe mostrar CERO referencias directas a packages