Pull to refresh

Comments 20

Второй недостаток здесь в том, что мы потенциально можем отделить объект-значение от родителькой сущности. Address может жить собственной жизнью, т.к. мы можем удалить Person из БД без удаления соответствующей строки Address

Для этого придумали каскадное удаление в частности и правила удаления по внешнему ключу в целом.

А что если в объекте-значении Address 100 полей? Заинлайнить все?
В DDD Aggregation Root для этого есть. Но, автор, видимо, о нём не слышал…
В вопросе объектов-значений и сущностей важное значение имеет следующее правило: всегда предпочитайте объекты-значения сущностям.
Это противоречит самому духу DDD. DDD призывает строить дизайн приложения исходя из предметной области. Т.е. выбор Entity vs Value Object делается исходя из уникальности\неуникальности.
У вас прям сборник вредных советов какой-то получился.
С адресом плохой пример. Дом снесли — адрес исчез, ну или «стал неактивен». А например цифру 2 отменить нельзя. Кроме того, у человека или организации может быть несколько адресов.
Имхо, проблема не в примере, а в правиле, которое этот пример иллюстрирует:
Объекты-значения не должны иметь собственной таблицы в БД.
В классической книге по DDD Эрика Эванса «Предметно-ориентированное программирование» приводится тот же самый пример про человека и адрес, а потом идёт раздел про оптимизацию, и там говорится, что объекты-значения легко подвергнуть денормализации и вставить внутрь таблицы объекта-сущности. Ни слова про то, что поступать так нужно всегда, там нет. Такой совет противоречит DDD. Имхо, вольный пересказ книги у автора статьи не удался.
Мне кажется, считать адрес объектом-значением можно, если он нужен только для информации и выводится один раз где-нибудь в профиле пользователя, а реальность адреса не имеет значения. Но фактически это самостоятельная сущность, никак не связанная с пользователем, и она может изменяться. Например, переименование улицы. Местоположение на карте осталось то же самое, этажность и номер дома те же, люди и организации из этого дома никуда не переехали, а текстовое представление адреса изменилось. Это аналогично изменению фамилии у человека.
Совершенно верно. В одних программах в рамках DDD адрес будет объектом-сущностью (когда нас интересует уникальность жилища; например, когда у каждого жилища есть какой-то рейтинг или история жильцов), а в других — объектом-значением.
ФИО — в подавляющем большинстве задач тоже объект-значение :)
Инлайнить значения в общую таблицу или создавать отдельную — вопрос тактический, вопрос локальной архитектуры. Тут много нюансов. Но если в отдельную таблицу, то пример идеологически неправильный (хотя технически может быть обоснован). Не в таблице Person должно быть полe AddressId, а в таблице Address поле PersonId, а поля Id быть не должно.
Заинлайнить хорошо когда связь один к одному, и когда не надо с этими полями работать, тоесть делать выборку всех людей с таким то зипкодом.
На хабре всерьёз разбирают отличия Value Object и Entity — приплыли…
Ничего плохого не вижу в том, чтобы у объекта-значения была отдельная таблица в СУБД и, следовательно, идентификатор для доступа к записи. Семантически при этом с записью можно работать как с объектом-значением. Допустим, у персоны есть адреса. Чтобы присвоить второй персоне такой же адрес, как и у первой, мы просто создаём новую запись в таблице и копируем значимые поля. В доменной модели это будет работать именно так, тип «Адрес» будет иметь семантику объекта-значения, а наличие идентификатора служит лишь для доступа к записи и «наружу» за пределы доменной модели не виден. Что плохого-то? Зачем инлайнить? Глупости какие.
Это у вас выходит уже не просто «Адрес», а отдельная сущность — «Адрес персоны», в которой можно выделить идентификатор (его нельзя прятать: он вам понадобится когда вы будете один из адресов удалять), связь с персоной и собственно адрес (объект-значение).

Аналогичный вопрос рассматривается в известной книге, а именно в пятой главе. Если коротко, то никаким образом наличие или отсутствие поля id не делает что-то сущностью или обьектом-значением. Речь там идет о том, чтобы не добавлять лишних идентификаторов и не усложнять работу с обьектами-значениями без необходимости.

Конкретно поле с именем id, конечно же, ни на что не влияет.

А вот наличие или отсутствие поля с семантикой главного идентификатора (=первичного ключа) как раз и разделяет сущности и объекты-значения.

На уровне объектов поля. Первичный ключ в таблице может и не проецироваться на поле объекта вовсе, или проецироваться (скажем, из-за особенностей ORM), но не участвовать в бизнес-логике, прежде всего в логике сравнения объектов-значений одного типа с другим, если нет гарантий "синглтонности" таких объектов для каждого значения, для каждого сочетания бизнес-полей.

Семантически неверно создавать две записи, отличающиеся только значением суррогатного идентификатора. Вы же не создаёте одинаковые записи для, например, датывремени? И не сравниваете датувремя по идентификатору? Не, бывают задачи когда нужно группировать записи по части значения датывремени типа "отчёт за год", но логически они ничем не отличаются от задач "отчёт по улице". Что для вас (ваших задач) значит "отредактировать адрес с id 12345678"? зачем этому адресу идентификатор?
Смешали ограничения накладываем на разработку с отображением объектов на БД в одну кучу. Ужас!
Sign up to leave a comment.

Articles