Сохранение изменений доменов - PullRequest
11 голосов
/ 21 сентября 2011

вот реальный пример, который приведет к моему вопросу: у меня есть AddCommentToArticleCommand, который имеет ArticleId, текст комментария и адрес электронной почты.Эта команда:

  • использует репозиторий статей для получения статьи (которая является сущностью домена)
  • , если статья существует, она вызывает article.AddComment (commentText, emailAddress), который добавляеткомментарий к статье и выдает исключение, когда это невозможно (из-за неверного формата электронной почты, статья была закрыта, комментарий не был заполнен или слишком длинный и т. д.)
  • , но теперь я не знаю, чтолучший способ сохранить добавленный комментарий?

Должен ли я сделать что-то вроде articleRepository.Save (article)?Но тогда зачем мне сохранять статью, если добавлен только комментарий?Или я могу сделать что-то вроде articleRepository.SaveComment (comment), который только сохранит комментарий?Или какой подход вы бы выбрали здесь?

Спасибо!

Ответы [ 2 ]

8 голосов
/ 22 сентября 2011

Как указывает MattDavey , в DDD вы обычно думаете о агрегированном жизненном цикле, а не о проблемах сохранения CRUD. Середина и конец жизни Агрегата обрабатываются соответствующим Хранилищем . Относительно вашего конкретного вопроса:

но теперь я не знаю, как лучше сохранить добавленный комментарий?

Лучший способ справиться с этим - найти надежный ORM и реализовать свой

articles.MakePersistent(article)

метод репозитория с использованием этого ORM. Хороший ORM будет реализовывать UnitOfWork , будет включать грязное отслеживание, отложенную загрузку и другие проблемы, связанные с сохранением, без ограничения объектов вашего домена. ORM знает, как избежать ненужных SQL INSERT / UPDATE при сохранении Aggregate . Ваши доменные объекты должны быть как можно более невежественными. Единственное ограничение, которое NHibernate, например, накладывает на ваши объекты, заключается в том, что они должны иметь закрытый конструктор по умолчанию. Кроме этого они могут быть простыми объектами POCO, не подозревающими обо всех проблемах с сохранением. Просто чтобы очистить, доменные объекты не должны иметь флагов IsTransient или IsDirty. И если вы обнаружите, что пишете код, использующий эти флаги, вы заново ставите колесо .

1 голос
/ 21 сентября 2011

В DDD часто бывает, что вы берете всю иерархию композиции из корня агрегата и рассматриваете ее как единый объект.Итак, приняв этот менталитет, «зачем мне сохранять статью, если был добавлен только комментарий?» , может показаться, что статья в целом изменилась, и представление статьи в базе данныхнесвежий.В идеале вы должны заменить всю композиционную иерархию в базе данных (с базой данных документов, это было бы хорошо), однако это может привести к проблемам с производительностью в реляционной БД.

В этом случае вы можете решить иметь хранилищепросмотрите состав объекта, соберите корень вниз и разумно решите, что делать с каждым компонентом.Вы можете использовать шаблон посетителя для итерации по объектам Comment, и в зависимости от того, являются ли они временными или грязными, решают сделать вставку или обновление, или просто оставить их в покое ..

Я надеюсь, что яЯ достаточно ясно объяснил концептуальные вещи:)

РЕДАКТИРОВАТЬ: Пример кода:

// In ArticleRepository...
public void Save(Article article)
{
    // IsTransient (as opposed to IsPersistant) means "has not yet been saved"...
    if (article.IsTransient)
    {
        DB.InsertArticle(article);
        // Inserting the article also inserts any comments / sub components...
    }
    else
    {
        // IsDirty means "has been modified since it was taken from the DB"...
        if (article.IsDirty)
        {
            DB.UpdateArticle(article);
        }

        foreach(var comment in article.Comments)
        {
            if(comment.IsTransient)
            {
                DB.InsertComment(article.Id, comment);
            }
            else
            {
                if (comment.IsDirty)
                {
                    DB.UpdateComment(comment);
                }
            }
        }
    }
}
...