我有一个常见的场景,我正在寻找对 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) 修改 Article 以要求 IEmailService(在 ctor 中?)或从对我的 DI 容器的静态引用中获取 EmailService
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,我无法再向 Article 实例添加评论。它也感觉不太自然,因为 AddComment 似乎是 Article 类型的一个明显的方法。
无论如何,我期待阅读输入。提前致谢。