Nel dibattito sui modelli di dominio Rich vs. Anemic, Internet è pieno di consigli filosofici ma di esempi autorevoli. L'obiettivo di questa domanda è quello di trovare linee guida definitive ed esempi concreti di opportuni modelli di progettazione basata sul dominio. (Idealmente in C #.)
Per un esempio del mondo reale, questa implementazione di DDD sembra essere sbagliata:
I modelli di dominio WorkItem di seguito non sono altro che sacchetti di proprietà, utilizzati da Entity Framework per un database code-first. Per Fowler, è anemico .
Il livello WorkItemService è apparentemente un errore comune dei Domain Services; contiene tutto il comportamento / business logic per WorkItem. Per Yemelyanov e altri, è procedurale . (pagina 6)
Quindi se il sotto è sbagliato, come posso farlo bene?
Il comportamento, ad esempio AddStatusUpdate o Checkout , dovrebbe appartenere alla classe WorkItem corretta?
Quali dipendenze dovrebbe avere il modello 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();
}
}
}
(Questo esempio è stato semplificato per essere più leggibile.Il codice è sicuramente ancora goffo, perché è un tentativo confuso, ma il comportamento del dominio è stato: stato di aggiornamento aggiungendo il nuovo stato alla cronologia degli archivi.Infine sono d'accordo con l'altro risposte, questo potrebbe essere gestito da CRUD.)
Aggiornamento
@AlexeyZimarev ha fornito la risposta migliore, un video perfetto sull'argomento in C # di Jimmy Bogard, ma apparentemente è stato spostato in un commento di seguito perché non forniva informazioni sufficienti al di là del collegamento. Ho una bozza preliminare dei miei appunti che riassumono il video nella mia risposta qui sotto. Non esitate a commentare la risposta con eventuali correzioni. Il video dura un'ora, ma vale la pena guardare.
Aggiornamento - 2 anni dopo
Penso che sia un segno della nascente maturità della DDD che, anche dopo averlo studiato per 2 anni, non posso ancora promettere di conoscere la "maniera giusta" per farlo. Il linguaggio onnipresente, le radici aggregate e il suo approccio al design comportamentale sono i preziosi contributi di DDD al settore. L'ignoranza di persistenza e l'individuazione di eventi causano confusione e penso che la filosofia del genere la trattiene da una più ampia adozione. Ma se dovessi fare di nuovo questo codice, con quello che ho imparato, penso che sarebbe simile a questo:
Ricevo ancora eventuali risposte a questo post (molto attivo) che fornisce un codice di best practice per un modello di dominio valido.