У меня есть общий сценарий, что я ищу некоторые рекомендации от людей, более опытных с DDD и Domain Modeling в целом.
Скажем, я начинаю строить механизм блога, и первое требование состоит в том, что после публикации статьи пользователи могут начинать публиковать комментарии к нему. Это начинается нормально и приводит к следующему дизайну:
public class Article
{
public int Id { get; set; }
public void AddComment(Comment comment)
{
// Add Comment
}
}
Мой MVC-контроллер сконструирован следующим образом:
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");
}
}
Теперь все работает отлично, и оно соответствует требованию. В следующей итерации мы получаем требование, чтобы каждый раз, когда был отправлен Комментарий, автор блога должен получить уведомление по электронной почте.
На данный момент у меня есть два варианта, о которых я могу думать. 1) Измените статью, чтобы потребовать IEmailService (в ctor?) Или получить EmailService из статической ссылки на мой контейнер DI
1a) Кажется довольно уродливым. Я считаю, что это нарушает некоторые правила модели домена, которые мои сущности знают о сервисах?
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) Также кажется уродливым, теперь я требую сконфигурированный контейнер DI, к которому обращаются статически.
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) Создайте службу IArticleService и переместите метод AddComment() на эту службу, а не на сам объект статьи.
Это решение чище, я считаю, но добавление комментария теперь менее доступно для поиска и требует, чтобы ArticleService выполнял работу. Кажется, что AddComment должен принадлежать самому классу Article.
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");
}
}
Поэтому я в основном ищу совет от людей, более опытных в области моделирования доменов. Если у меня отсутствует более очевидное решение, сообщите мне:)
Мне вообще не нравятся оба решения, если честно, потому что опция Service менее понятна. Я больше не могу добавлять комментарий к экземпляру статьи без наличия доступной статьи. Это также кажется менее естественным, поскольку AddComment кажется таким очевидным методом для типа статьи.
В любом случае я с нетерпением жду чтения ввода. Спасибо заранее.