Неизменные объекты и DDD идут вместе?

18

Рассмотрим систему, которая использует DDD (также: любую систему, которая использует ORM). Смысл любой системы реалистично, почти в каждом случае использования, состоит в том, чтобы манипулировать этими объектами домена. В противном случае нет никакого реального эффекта или цели.

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

Я вижу выгоду от использования неизменяемых объектов, но в этом смысле я никогда не вижу полезного случая использования неизменяемых объектов. Это неправильно?

Стивен Эверс
источник

Ответы:

16

Вычисления с использованием неизменяемых объектов (как в функциональном программировании) не обязательно подразумевают сохранение каждого сгенерированного объекта!

Стивен А. Лоу
источник
Я не вижу случая, когда этот сценарий использует неизменные объекты в любом случае - так что они будут там без какой-либо конкретной цели. Я ошибаюсь?
Стивен Эверс
1
я думал, что неизменные объекты будут полезны для промежуточных вычислений (в параллельных потоках)
Стивен А. Лоу
11

Означает ли неизменяемость в домене, что она должна быть неизменной в базе данных? Например, рассмотрим следующее, предполагая, что клиент всегда имеет один адрес:

customer.address = new Address('My Castle', 'Kings street');
customer_repo.save(customer);

теперь запускается следующий sql, учитывая, что идентификатор клиента равен 1:

INSERT INTO addresses (customer_id, name, street)
VALUES (1, 'My Castle', 'Kings street');

Теперь в адрес внесены следующие изменения:

customer.address = new Address('Pauper palace', 'Outlands');
customer_repo.save(customer);

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

UPDATE addresses SET name='Pauper palance', street='Outlands'
WHERE customer_id = 1;

Таким образом вы избежите накладных расходов на отдельную инструкцию DELETE AND INSERT. Также я думаю, что некоторые РСУБД имеют ЗАМЕНУ ВСТАВКИ или что-то в этом роде. MySql имеет ЗАМЕНУ .

andho
источник
+1 Я согласен с вами по общему принципу: я не понимаю, почему неизменяемые доменные объекты обязательно должны означать неизменные строки БД.
Андрес Ф.
В приведенном выше случае, если нам когда-либо понадобилось изменить атрибут города класса адресов для данного клиента, как бы мы справились с этим? Далее предположим, что у клиента может быть несколько адресов, так что связь между клиентом и адресами может быть один ко многим
Sudarshan
1
@Sudarshan - это просто способ создать «неизменяемый объект значения», который не может быть неизменным в базе данных. По причинам производительности. С каждой ситуацией нужно обращаться конкретно. Я предпочитаю Event Sourcing для своего домена сейчас, но я отчасти зависим от него.
andho
@Sudarshan, чтобы конкретно ответить на ваш вопрос, вы просто запускаете запрос на обновление, который обновляет строку до нового значения. Если это один ко многим, то адреса будут иметь своего рода идентификатор в корне клиента, который будет использоваться для его уникальной идентификации в БД. Затем этот идентификатор и customer_id будут использоваться для обновления этой строки в таблице адресов.
andho
@andho «это просто способ создать« неизменяемый объект значения », который не может быть неизменным в базе данных». это действительно сделало мой день спасибо
Сударшан
6

В DDD неизменяемые объекты в значительной степени приравниваются к объектам-значениям. Эти объекты не являются сущностями, у них нет идентичности. Поэтому я всегда сохраняю объекты-значения как столбцы сущности, в которой они содержатся (для N / Hibernate вы можете использовать компоненты для этого). У них нет собственного стола.

guillaume31
источник
4

Это зависит от того, как неизменяемый объект отображается в базе данных. Если это просто компонент типа DateTime (из библиотеки Joda Time), то изменение значения приведет к обновлению, а не к вставке. Однако, если неизменяемый объект более сложный, требующий строки в таблице, у вас есть проблема с раздуванием.

Я полагаю, хотя это слабый аргумент, вы могли бы реализовать контрольный журнал таким образом. Каждое изменение в неизменяемости может быть отслежено через вкладыши. Есть много лучших способов сделать это, хотя.

В общем, наличие неизменяемых доменных объектов (а не просто их компонентов) кажется немного несовместимым с постоянством.

Гэри Роу
источник
Не за что. Компоненты очень полезны, поскольку они позволяют составлять доменные объекты по-разному из одних и тех же базовых данных. Проблемы связаны с обеспечением неизменности. Лично я бы относился к объектам домена как изменяемым (за исключением полей первичного ключа) и делал бы это простым.
Гэри Роу
«В целом наличие неизменяемых доменных объектов (а не просто их компонентов) кажется чем-то вроде несовпадения с постоянством». По вашему мнению, где нам нужно иметь объекты-значения, которые не должны моделироваться как компоненты (терминология Hibernate)? --- Извините, я неправильно набрал последний комментарий и, следовательно, удалил его.
Сударшан
Избегайте компонентов, когда один объект полностью представлен строкой, и ни один из данных не используется другим объектом домена.
Гэри Роу
4

Это зависит от домена. DDD не указывает, что парадигма программирования является объектно-ориентированной. Однако объектно-ориентированная парадигма хорошо подходит для типичного приложения, которое необходимо сохранить в базе данных.

DDD просто заявляет, что вы должны строить свое программное обеспечение на основе модели предметной области, которая представляет собой реальную проблему, которую программное обеспечение пытается решить. Если бы эта проблема была, например, математической по своей природе, то реализация доменного уровня с использованием функционального программирования и неизменных структур данных имела бы большой смысл.

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

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

  • У вас нет вездесущего языка. Язык и понятия в модели предметной области не соответствуют тому, что используют эксперты предметной области.

Примечание: DDD использует неизменяемые объекты, где это уместно, они просто называются объектами значений.

Поэтому я не говорю, что вы не можете создать приложение базы данных, используя чисто функциональные структуры данных, и я не говорю, что вы не должны этого делать. Я просто не думаю, что вы можете назвать это DDD, в зависимости от типа приложения

Пит
источник
Питер, отличный ответ. Не могли бы вы взглянуть на мой вопрос здесь stackoverflow.com/questions/13783666/… и помочь мне разобраться в моей проблеме. Я думаю, что объекты с неизменной ценностью отлично подходят для программ, не связанных с предприятием. По моему мнению, объекты большинства корпоративных приложений изменчивы. Представьте себе, что у вас есть неизменяемый объект значений с глубоким вложением ... ContactInfo-> PhysicalLocation-> Address, и вы хотите обновить почтовый индекс ... создание всего графа объектов кажется мне антихристом, а не просто антипаттерном. что вы думаете?
Пепито Фернандес
3

Если вы используете ORM, например Hibernate / NHibernate, вы можете установить каскадную опцию для автоматического удаления осиротевших объектов. Если у человека есть объект значения «Адрес», при изменении адреса новый будет сохранен, а старый удален, поскольку теперь он потерян.

Майк Роули
источник
0

Объекты значений почти всегда неизменны в DDD, и шаблон flyweight можно использовать для сохранения дублирования этого объекта значений в памяти, как это делает .NET со строками. Основным компромиссом является память с одной стороны, а с другой стороны - творческая эффективность. С шаблоном flyweight, сравнение на основе значений должно быть выполнено, чтобы определить, находится ли какой-либо новый или восстановленный объект значения уже в кэше flyweight, но любое другое сравнение после этой точки, как правило, может быть безопасно выполнено посредством ссылки, так как применяется один экземпляр. В любом случае, независимо от того, используется весовой вес или нет, объекты-значения по-прежнему остаются неизменяемыми, поскольку они имеют только внутреннюю идентичность и, следовательно, изменение их значения может изменить их идентичность.

jpierson
источник
-1

Есть еще один способ использовать неизменяемые объекты ...

Вместо того, чтобы хранить значения 5.0, 6.0, 7.0, 8.0 и копировать всю запись каждый раз, вы можете вместо этого сохранить что-то вроде этого: 5.0, +1.0, +1.0, +1.0, а затем правильно построить зависимости, чтобы восстановить последовательность 5.0 6,0, 7,0, 8,0. Таким образом, небольшие модификации занимают небольшое количество памяти ...

ТР1
источник