Domanda

Ho uno scenario comune che sto cercando qualche indicazione da parte di persone con più esperienza con DDD e di dominio di modellazione in generale.

Dire che iniziare la costruzione di un motore di blog, e il primo requisito è che, dopo un articolo è pubblicato, gli utenti possono 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
    }
}

Il mio controller MVC è stato 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 un requisito che ogni volta che un commento viene pubblicato, l'autore del blog dovrebbe ottenere una e-mail che lo informa.

A questo punto, ho 2 scelte che mi viene in mente. 1) Modificare l'articolo per richiedere un'IEmailService (nel ctor?) O di ottenere un EmailService da un riferimento statico al mio contenitore DI

1 bis) sembra abbastanza brutto. Credo che rompe alcune regole modello di dominio che i miei soggetti sono a conoscenza di 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) sembra anche brutto, ora richiedono un contenitore DI configurato a cui si accede in modo statico.

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) Creazione di un IArticleService e spostare il metodo addComment () a questo servizio, invece di sull'articolo entità in sé.

Questa soluzione è più pulita credo, ma l'aggiunta di un commento è ora meno rilevabile e richiede un ArticleService per eseguire il lavoro. Sembra addComment dovrebbe appartenere sull'articolo classe 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 io sono fondamentalmente cerco consigli da persone con più esperienza nella modellazione di dominio. Se mi manca una soluzione più ovvia per favore fatemelo sapere:)

Io generalmente piace entrambe le soluzioni per essere onesti, perché l'opzione servizio è meno rilevabile. Non posso più aggiungere un commento a un'istanza di un articolo senza avere un ArticleService disponibili. Si sente anche meno naturale, dal momento che addComment sembra un metodo così evidente dal tipo di articolo.

In ogni caso non vedo l'ora di leggere l'input. Grazie in anticipo.

È stato utile?

Soluzione

Credo che questo particolare problema può essere risolto elegantemente con un Domain Event .

Altri suggerimenti

Avete considerato avente essenzialmente il controller articolo passare un messaggio su / inviare un evento? Quindi qualsiasi "articolo-pubblicato-event-ascoltatori" consumerebbero quel messaggio e rispondere di conseguenza; nel caso specifico, un notificatore di posta elettronica sarebbe essere in ascolto per quegli eventi ed essere configurato per farlo. In questo modo la pubblicazione di articoli bit non hanno bisogno di sapere nulla circa l'e-mail di notifica bit.

Guardando attraverso questo eccellente domanda, mi ha portato a leggere impiegando il modello di dominio modello da Udi su MSDN.

HTH aiuta gli altri utenti.

I cercato di capire come porre questa stessa domanda, ma è riuscito a confondere me stesso più volte. La tua domanda non è certo! Grazie

Senza usare gli eventi di dominio, è possibile utilizzare il modello a doppia spedizione e mettere la logica addComment all'interno di un dominio del servizio.

Ecco come sarebbe simile a:

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");
    }
}

Se si preferisce, è possibile mantenere la logica Aggiunta Commento alla addComment dell'articolo, e invece rendere il servizio Domain in qualcosa di simile ICommentAddedProcessor con un metodo CommentAdded () e hanno addComment sull'articolo fare un commento e un ICommentAddedProcessor.

Credo che ogni volta che l'esperto di dominio utilizza la parola "quando" si deve considerare di dominio Eventi o un bus evento, questo è stato un classico esempio in questo senso.

Ho scritto una rispondere che descrive quando utilizzare gli autobus di eventi, potrebbe essere una buona lettura intorno a questo argomento

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top