How to avoid anemic domain models, or when to move methods from the entities into services

心已入冬 提交于 2019-12-02 14:03:18

I think this particular issue can be solved elegantly with a Domain Event.

Have you considered having the article controller essentially pass a message up / post an event? Then any "article-posted-event-listeners" would consume that message and respond accordingly; in your specific case, an email notifier would be listening for those events and be configured to do so. This way the article posting bits don't need to know anything about the email notifying bits.

Looking through this excellent question, has lead me to read Employing the Domain Model Pattern from Udi on MSDN.

HTH helps other users.

I been trying to work out how to ask this same question but managed to confused myself several times. Your question certainly is not! Thanks

Without using domain events, you can use the Double Dispatch pattern and put the AddComment logic inside a Domain Service.

This is how it would look like:

public class Article
{
    public void AddComment(Comment comment, IAddCommentProcessor commentProcessor)
    {
        commentProcessor.AddComment(this, comment);
    }
}

public interface IAddCommentProcessor
{
    void AddComment(Article article, Comment comment);
}

public class AddCommentAndEmailProcessor : IAddCommentProcessor
{
    private readonly _emailService;
    public AddCommentAndEmailProcessor(EmailService emailService)
    {
        _emailService = emailService;
    }

    public void AddComment(Article article, Comment comment)
    {
        // Add Comment

        // Email
        _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);
        article.AddComment(comment, new AddCommentAndEmailProcessor(ServiceLocator.GetEmailService())); // Or you can use DI to get the Email Service, or any other means you'd prefer
        _repository.Save(article);
        return RedirectToAction("Index");
    }
}

If you prefer, you can keep the Adding Comment logic on the AddComment of Article, and instead make the Domain Service into something like ICommentAddedProcessor with a CommentAdded() method and have AddComment on Article take a Comment and a ICommentAddedProcessor.

Sudarshan

I think whenever the domain expert uses the word "when" one must consider Domain Events or an event bus, this was a classic example in that sense.

I have written a detailed answer which describes when to use event buses, it might be a good read around this topic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!