En el debate de los modelos de dominio Rich vs. Anemic, Internet está lleno de consejos filosóficos, pero carece de ejemplos autorizados. El objetivo de esta pregunta es encontrar pautas definitivas y ejemplos concretos de modelos adecuados de diseño impulsado por dominio. (Idealmente en C #.)
Para un ejemplo del mundo real, esta implementación de DDD parece ser incorrecta:
Los siguientes modelos de dominio de WorkItem no son más que bolsas de propiedades, utilizadas por Entity Framework para una base de datos de código primero. Según Fowler, es anemic .
La capa WorkItemService es aparentemente una percepción errónea común de los Servicios de Dominio; contiene toda la lógica de comportamiento / negocio para el artículo de trabajo. Según Yemelyanov y otros, es de procedimiento . (pág. 6)
Entonces, si lo que sigue es incorrecto, ¿cómo puedo corregirlo?
El comportamiento, es decir, AddStatusUpdate o Checkout , debería pertenecer a la clase WorkItem ¿correcto?
¿Qué dependencias debería tener el modelo WorkItem?
publicclassWorkItemService:IWorkItemService{privateIUnitOfWorkFactory_unitOfWorkFactory;//usingUnityfordependencyinjectionpublicWorkItemService(IUnitOfWorkFactoryunitOfWorkFactory){_unitOfWorkFactory=unitOfWorkFactory;}publicvoidAddStatusUpdate(intworkItemId,intstatusId){using(varunitOfWork=_unitOfWorkFactory.GetUnitOfWork<IWorkItemUnitOfWork>()){varworkItemRepo=unitOfWork.WorkItemRepository;varworkItemStatusRepo=unitOfWork.WorkItemStatusRepository;varworkItem=workItemRepo.Read(wi=>wi.Id==workItemId).FirstOrDefault();if(workItem==null)thrownewArgumentException(string.Format(@"The provided WorkItem Id '{0}' is not recognized", workItemId), "workItemId");
var status = workItemStatusRepo.Read(s => s.Id == statusId).FirstOrDefault();
if (status == null)
throw new ArgumentException(string.Format(@"The provided Status Id '{0}' is not recognized", statusId), "statusId");
workItem.StatusHistory.Add(status);
workItemRepo.Update(workItem);
unitOfWork.Save();
}
}
}
(Este ejemplo se simplificó para que sea más legible. El código definitivamente es torpe, porque es un intento confuso, pero el comportamiento del dominio fue: actualizar el estado agregando el nuevo estado al archivo histórico. En última instancia, estoy de acuerdo con el otro respuestas, esto podría ser manejado por CRUD.)
Actualizar
@AlexeyZimarev dio la mejor respuesta, un video perfecto sobre el tema en C # por Jimmy Bogard, pero aparentemente se trasladó a un comentario a continuación porque no proporcionó suficiente información más allá del enlace. Tengo un borrador de mis notas que resumen el video en mi respuesta a continuación. Por favor, siéntase libre de comentar la respuesta con cualquier corrección. El video dura una hora pero vale la pena verlo.
Actualización - 2 años después
Creo que es un signo de la madurez naciente de DDD que incluso después de estudiarlo durante 2 años, todavía no puedo prometer que conozco la "forma correcta" de hacerlo. El lenguaje ubicuo, las raíces agregadas y su enfoque del diseño basado en el comportamiento son las valiosas contribuciones de DDD a la industria. La ignorancia de la persistencia y la fuente de eventos causa confusión, y creo que una filosofía como esa lo retiene de una adopción más amplia. Pero si tuviera que hacer este código otra vez, con lo que he aprendido, creo que se vería algo como esto:
Todavía recibo con agrado cualquier respuesta a esta publicación (muy activa) que proporcione cualquier código de mejores prácticas para un modelo de dominio válido.