Ho uno scenario comune che sto cercando alcune indicazioni da persone più esperte con DDD e Domain Modeling in generale.Come evitare i modelli di dominio anemici o quando spostare i metodi dalle entità nei servizi
Dire che inizio a creare un motore per blog e il primo requisito è che dopo aver pubblicato un articolo, gli utenti possano iniziare a postare commenti su di esso. Questo inizia bene, e porta alla seguente disegno:
public class Article
{
public int Id { get; set; }
public void AddComment(Comment comment)
{
// Add Comment
}
}
mio MVC regolatore è progettato in questo modo:
public class ArticleController
{
private readonly IRepository _repository;
public ArticleController(IRepository repository)
{
_repository = repository;
}
public void AddComment(int articleId, Comment comment)
{
var article = _repository.Get<Article>(articleId);
article.AddComment(comment);
_repository.Save(article);
return RedirectToAction("Index");
}
}
Ora tutto funziona bene, e soddisfa il requisito. Prossima iterazione otteniamo il requisito che ogni volta che viene pubblicato un commento, l'autore del blog debba ricevere un'e-mail che lo avvisa.
A questo punto, ho 2 scelte a cui posso pensare. 1) Modificare l'articolo per richiedere un IEmailService (nel ctor?) O ottenere un EmailService da un riferimento statico al mio contenitore DI
1a) Sembra abbastanza brutto. Credo che rompa alcune regole del modello di dominio che le mie entità sono a conoscenza dei servizi?
public class Article
{
private readonly IEmailService _emailService;
public Article(IEmailService emailService)
{
_emailService = emailService;
}
public void AddComment(Comment comment)
{
// Add Comment
// Email admin
_emailService.SendEmail(App.Config.AdminEmail, "New comment posted!");
}
}
1b) Inoltre sembra brutto, ora richiede un contenitore DI configurato a cui si accede staticamente.
public class Article
{
public void AddComment(Comment comment)
{
// Add Comment
// Email admin
var emailService = App.DIContainer.Resolve<IEmailService>();
emailService.SendEmail(App.Config.AdminEmail, "New comment posted!");
}
}
2) Creare un IArticleService e spostare il metodo addComment() a questo servizio, invece di sull'articolo entità stessa.
Questa soluzione è più pulita, ma l'aggiunta di un commento è ora meno rilevabile e richiede un ArticleService per eseguire il lavoro. Sembra che AddComment debba appartenere alla classe Article stessa.
public class ArticleService
{
private readonly IEmailService _emailService;
public ArticleService(IEmailService emailService)
{
_emailService = emailService;
}
public void AddComment(Article article, Comment comment)
{
// Add comment
// Email admin
_emailService.SendEmail(App.Config.AdminEmail, "New comment posted!");
}
}
public class ArticleController
{
private readonly IRepository _repository;
private readonly IArticleService _articleService;
public ArticleController(IRepository repository, IArticleService articleService)
{
_repository = repository;
_articleService = articleService;
}
public void AddComment(int articleId, Comment comment)
{
var article = _repository.Get<Article>(articleId);
_articleService.AddComment(article, comment);
_repository.Save(article);
return RedirectToAction("Index");
}
}
Quindi sono fondamentalmente alla ricerca di consigli da persone più esperte nella modellazione di domini. Se mi manca una soluzione più ovvia per favore fatemelo sapere :)
In genere non mi piacciono entrambe le soluzioni, perché l'opzione Servizio è meno rilevabile. Non è più possibile aggiungere un commento a un'istanza di un articolo senza disporre di un articoloServizio disponibile. Sembra anche meno naturale, dal momento che AddComment sembra un metodo così ovvio per il tipo di articolo.
In ogni caso non vedo l'ora di leggere l'input. Grazie in anticipo.
+1 per soluzione # 2 – JuanZe
+1 per una chiara domanda – Rippo