DDD и объекты значения. Изменчивые Объекты Значения - хороший кандидат для Non Aggr. Корневая сущность?

9

Вот небольшая проблема

Иметь сущность со значением объекта. Не проблема. Я заменяю объект-значение новым, затем nhibernate вставляет новое значение и теряет значение старого, а затем удаляет его. Хорошо, это проблема.

Застрахованным является моя сущность в моем домене. У него есть коллекция адресов (объектов значения). Одним из адресов является MailingAddress. Когда мы хотим обновить почтовый адрес, скажем, почтовый индекс был неправильным, следуя доктрине г-на Эванса, мы должны заменить старый объект новым, так как он неизменный (верно, объект значения?).

Но мы не хотим удалять строку, потому что PK этого адреса является FK в таблице MailingHistory. Итак, следуя доктрине г-на Эванса, мы в значительной степени облажались. Если я не создаю адреса своих сущностей, мне не нужно «заменять» его и просто обновлять его член почтового индекса, как в старые добрые времена.

Что бы вы мне предложили в этом случае? На мой взгляд, ValueObjects полезны только тогда, когда вы хотите инкапсулировать группу столбцов таблицы базы данных (компонент в nhibernate). Все, что имеет постоянный идентификатор в базе данных, лучше сделать его сущностью (не обязательно совокупным корнем), чтобы вы могли обновлять ее элементы, не воссоздавая весь граф объектов, особенно если это объект с глубокой вложенностью.

Вы согласны? Разрешено ли мистеру Эвансом иметь изменяемый объект значения? Или объект изменяемого значения является кандидатом в сущность?

Спасибо

Пепито Фернандес
источник
2
Есть ли такая вещь, как «объект изменяемого значения»? У меня всегда было впечатление, что объекты ценности неизменны.
Herby
@ herby Я думаю, у вас мог бы быть изменяемый объект, представляющий объект значения DDD в коде, но вы должны учитывать, что после того, как вы изменили объект, он больше не ссылается на тот же объект логического значения DDD, а на новый. Это может быть желательным, но это рецепт для путаницы в imo - создание значений объектов неизменяемых в коде является разумным соглашением.
MattDavey

Ответы:

8

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

По словам Мартина Фаулера (который в свою очередь цитирует Эрика Эванса)

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

Причина, по которой ваш адрес стал объектом значения:

Если ваш адрес изменчив, вы, вероятно, испортите свою историю рассылки в конце. Например, если вы отправляете товары клиенту, вы не можете быть уверены, на какой адрес вы действительно что-то отправляли в прошлом, если адрес, на который ссылается ваша таблица MailingHistory, был изменен.

Запись MailingHistory, которую мы отправили A764 по адресу 657, может означать, что вчера мы отправили статью A764 в Бостон, а завтра отправили статью A764 в Нью-Йорк .

Если почтовый адрес был изменен, нет необходимости удалять старый. Сохраните его и отметьте как неактивный , а новый как активный .


Конечно, вы можете рассматривать свой адрес как сущность, но только при обновлении он не изменит фактическое место, на которое ссылается адрес, а, следовательно, позволит только исправить опечатки.

Если вы уверены, что можете это сделать, то использование Entity будет возможно.


Но лучшее решение IMHO - не ссылаться на адрес Entity в вашей истории рассылки, а вместо этого сохранять конкретный адрес непосредственно в вашей таблице истории рассылки (в основном копируя данные адреса).

Таким образом, вы всегда будете знать, куда вы отправили свои материалы (или что вы отправляете по почте), и, поскольку вы будете использовать изменяемую сущность, ваша таблица адресов не будет загромождена.

Я работал с / на нескольких системах ERP, и почти все они использовали этот подход.

У вас будет некоторая избыточность в вашей базе данных, но это самый прагматичный способ, IMHO.

леность
источник
Это, наверное, самое безболезненное решение. Только если вы ожидаете, что для будущих каналов связи потребуются дополнительные столбцы, а ваша база данных слишком велика ALTER, использование сущностей в отдельных таблицах может оказаться необходимым. Это, в свою очередь, требует таких стратегий, как «всегда присоединяйся к новейшему адресу / телефону / электронной почте» в своих SELECTзапросах, которые сложно поддерживать и эффективно поддерживать . Сохраняйте это простым, если это вообще возможно.
Тимо
@Timo «всегда присоединяйтесь к новому адресу / телефону / электронной почте» не сложно, если вы немного денормализуете свои данные, просто добавив active-flag. Конечно, вы должны всегда использовать их and active = trueв своих объединениях, поддерживать флаг в актуальном состоянии и добавлять ограничения в свою таблицу, чтобы, например, только один адрес электронной почты для каждого клиента мог установить этот флаг в значение true.
ленивец
Это вводит проблему деактивации предыдущего. Если вы заменили «текущий» адрес объекта вашего экземпляра в коде и перейдете к коду доступа к данным, то он не будет знать (1), есть ли новый или нет, (2) каков потенциальный старый один был. Таким образом, каждая операция сохранения должна будет выполнять что-то замысловатое, например «сначала перейти и деактивировать все связанные адреса в базе данных», а затем сохранить текущий с помощью active=true. Это не то, что я бы назвал простым, именно поэтому мне нравится ваше решение.
Тимо
2

Я вижу 2 вещи:

  1. Допустимо ли изменение почтового индекса на запись истории? Я думаю, что было бы логично, чтобы запись истории указывала на старый неизмененный адрес, так что вы знаете, что отправляете его по неправильному адресу.

  2. В тот момент, когда MailingHistory имеет FK на адресе, адрес перестает быть объектом значения и становится сущностью. Значимые объекты не имеют идентичности, что позволяет другим сущностям ссылаться на эту идентичность. Вы можете иметь адреса в одной таблице, на которую указывают другие таблицы, но единственным эффектом является экономия места. С точки зрения предметной области, если две сущности имеют ссылку на один и тот же тип объекта-значения, они не делятся какой-либо информацией.

Euphoric
источник
2

IMO объект адреса - это объект в вашем домене. Он разделяется несколькими сущностями, имеет собственную идентификацию и уникален для всей системы.

Эванс говорит:

Объект, определяемый в первую очередь своей идентичностью, называется сущностью.

margabit
источник
Доменные идентичности, по моему мнению, не имеют ничего общего с постоянством идентичности. По книге мистера Эвана.
Пепито Фернандес
Вы правы. Я редактирую свой ответ. Я имею в виду, что адрес объекта имеет значение в этом конкретном домене, он уникален. ИМО Внешний ключ и Первичный ключ являются признаком того, что на самом деле это уникальный объект во всем домене, поэтому он имеет идентичность.
Margabit
1
«объект адреса ... имеет свою идентичность» - какой атрибут адреса однозначно его идентифицирует? Ни один из атрибутов адреса не является уникальным, но комбинация атрибутов служит идентификатором. Это само определение объекта значения
MattDavey
@MattDavey: это хороший вывод, но я запутался, когда Тони сказал: «Мы не хотим удалять строку, потому что PK этого адреса - это FK в таблице MailingHistory». Для меня это означает, что объект Address также имеет значение вне агрегата «застрахованный». Это указывает на то, что объект Address не должен быть объектом ValueObject. Что вы думаете?
Margabit
Можем ли мы сказать, что Value Objects неизменно будет полностью принадлежать составу (UML) родителю? Кроме того, Объект Значения не имеет смысла без его Родителя и не может быть разделен между Родителями?
Сударшан