我有一个常见的场景,我正在寻找一些有关DDD和领域建模更有经验的人的一些指导。如何避免贫血域模型或何时将方法从实体移动到服务中
假设我开始构建博客引擎,第一个要求是在发布文章后,用户可以开始发布评论。这将启动罚款,并导致了以下设计:
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");
}
}
所以,我基本上寻找更多领域建模经验的人的意见。如果我错过了一个更明显的解决方案,请让我知道:)
我通常不喜欢这两种解决方案是诚实的,因为服务选项不易发现。如果没有可用的ArticleService,我不能再向文章的实例添加评论。它也感觉不那么自然,因为AddComment看起来就像是一种明显的Article类型的方法。
无论如何,我期待阅读输入。提前致谢。
+1的解决方案#2 – JuanZe 2009-09-28 19:02:57
+1很好看的一个清晰的问题 – Rippo 2010-02-01 08:01:23