Как смоделировать отношения объекта значения?
Контекст:
У меня есть книга сущностей. Книга может иметь одно или несколько описаний. Описания являются ценностными объектами.
проблема:
Описание может быть более конкретным, чем другое описание. Например, если описание содержит содержание книги и то, как выглядит обложка, она более конкретна, чем описание, в котором обсуждается только то, как выглядит обложка. Я не знаю, как смоделировать это и как сохранить репозиторий. Это не обязанность книги или описания книги, чтобы знать эти отношения. Некоторый другой объект может обработать это и затем попросить хранилище сохранить отношения. Но BookRepository.addMoreSpecificDescription(Description, MoreSpecificDescription) кажется трудным для сохранения в хранилище.
Как такая вещь обрабатывается в DDD?
3 ответа
Два других ответа - одно направление (+1 к слову). Я приду после того, как вы отредактируете исходный вопрос, вот мои два цента...
Я определяю объект Value как объект с двумя или более свойствами, которые могут (и есть) совместно использоваться другими объектами. Они могут быть разделены только в пределах одного Агрегированного Корня, это тоже хорошо. Просто тот факт, что они могут (и являются) разделены.
Чтобы использовать ваш пример, вы определяете "Описание" как объект значения. Это говорит мне о том, что "Описание" с несколькими свойствами может быть общим для нескольких Книг. В реальном мире это не имеет смысла, поскольку все мы знаем, что каждая книга имеет уникальные описания, написанные мастером, который написал или опубликовал книгу. Хехе. Итак, я бы сказал, что Описания на самом деле не являются объектами значений, но сами являются дополнительными объектами сущностей в пределах границ вашей совокупной корневой сущности книги (вы можете иметь несколько сущностей в пределах одной совокупной корневой сущности). Даже переизданные книги, более новая редакция и т. Д. Имеют немного отличающиеся описания, описывающие это небольшое изменение.
Я полагаю, что это отвечает на ваш вопрос - создайте описания объектов-сущностей и защитите их за основным корнем объекта сущности книги (например, Book.GetDescription ()...). Остальная часть этого ответа посвящена тому, как я работаю с объектами-значениями в репозиториях, для тех, кто читает этот пост...
Для хранения объектов-значений в репозитории и их извлечения мы начинаем вторгаться на ту же территорию, с которой я боролся, переходя от подхода моделирования "сначала к базе данных" к подходу DDD. Я сам боролся с этим вопросом о том, как сохранить объект значения в БД и получить его без идентификатора. Пока я не отступил и не понял, что я делаю...
В доменно-управляемом дизайне вы моделируете объекты значения в своем домене, а не в хранилище данных. Это ключевая фраза. Это означает, что вы не проектируете объекты-значения, которые будут храниться как независимые объекты в хранилище данных, вы можете хранить их по своему усмотрению!
Давайте возьмем обычный DDD -пример Value Objects, который является Address (). DDD представляет, что почтовый адрес является идеальным примером объекта-значения, так как определение объекта-значения является объектом суммирования свойств которого для создания уникальности объекта. Если свойство изменяется, это будет другой объект значения. И тот же объект значения (сумма его свойств) может быть разделен между другими сущностями.
Почтовый адрес - это местоположение, длинный / лат определенного места на планете. По этому адресу могут жить несколько человек, и когда кто-то переезжает, новые люди, занимающие один и тот же почтовый адрес, теперь используют один и тот же объект значения.
Итак, у меня есть объект Person() с объектом Mailing Address(), который содержит информацию об адресе. Он защищен моим агрегатным корнем Person() с помощью методов / сервисов get / update / create.
Теперь, как мы можем хранить это и делиться этим среди людей в одном доме? Ах, в чем заключается DDD - вы не моделируете свое хранилище данных прямо из DDD (хотя это было бы неплохо). При этом вы просто создаете одну таблицу, которая представляет ваш объект Person, и в нем есть столбцы для вашего почтового адреса. Задача вашего репозитория заключается в том, чтобы повторно гидрировать эту информацию обратно в ваш объект Person() и Mailing Address() из хранилища данных и разделить ее во время операций создания / обновления.
Да, у вас будут дубликаты данных в вашем хранилище данных. Все три объекта Person() с одним и тем же почтовым адресом теперь имеют три отдельные копии данных этого объекта-значения - и это нормально! Объекты-значения предназначены для простого копирования и удаления. "Копия" - это оптимальное слово в пьесе DDD.
Подводя итог, можно сказать, что Domain Drive Design - это моделирование вашего домена для представления фактического бизнес-использования объектов. Вы моделируете сущность Person() и объект значения Mailing Address по отдельности, так как они представлены в вашем приложении по-разному. Вы сохраняете им скопированные данные, которые являются дополнительными столбцами в той же таблице, что и ваша таблица Person.
Все вышеперечисленное строго-DDD. Но DDD - это просто "предложения", а не правила, по которым нужно жить. Вот почему вы свободны делать то, что делали я и многие другие, что-то вроде стиля DDD. Если вам не нравятся скопированные данные, вы можете создать отдельную таблицу для Mailing Address() и прикрепить к ней столбец Identity, а также обновить свой объект Mailing Address(), чтобы теперь иметь эту идентичность - зная, что вы используете эту идентификацию только для связывания ее с другими объектами Person(), которые ее разделяют (лично мне нравится третья таблица отношений "многие ко многим", чтобы поддерживать скорость запросов). Вы бы замаскировали эту Идентичность (то есть внутренний модификатор) от раскрытия вне вашего Агрегированного Корня / Домена, чтобы другие слои (например, Приложение или Пользовательский интерфейс) не знали о столбце Идентичности MailingAddress, если это возможно. Кроме того, я бы создал специальный репозиторий только для Mailing Address и использовал бы ваш слой PersonService, чтобы объединить их в правильный объект Person.MailingAddress().
Извините за напыщенную речь...:)
Во-первых, я думаю, что отзывы должны быть юридическими лицами.
Во-вторых, почему вы пытаетесь смоделировать отношения между обзорами? Я не вижу естественных отношений между ними. "Более конкретно чем" слишком расплывчато, чтобы быть полезным в качестве отношений.
Если вам трудно моделировать ситуацию, это говорит о том, что, возможно, нет никаких отношений.
Я согласен с Джейсоном. Я не знаю, каково ваше обоснование для создания объектов оценки отзывов.
Я ожидаю, что BookReview будет иметь BookReviewContentItems, чтобы у вас мог быть метод для вызова BookReview, чтобы определить, достаточно ли он специфичен, где метод решает на основе запроса своей коллекции элементов контента.