Объекты в доменном дизайне - PullRequest
5 голосов
/ 24 февраля 2012

Я читаю книгу Эрика Эванса о DDD, и у меня есть вопрос к следующей цитате.Как вы делаете свой equals() метод, когда вы не должны использовать атрибуты?Я использую JPA, и у меня есть атрибут id, который уникален, но он не установлен, пока вы на самом деле не сохраните сущность.Ну так что ты делаешь?Я реализовал метод equals на основе атрибутов, и я понимаю, почему этого не следует делать, потому что в моем проекте это не удалось.

Раздел о сущностях:

Когда объект отличается по своей идентичности, а не по атрибутам, это делает его основным для его определения в модели.Сохраняйте определение класса простым и сфокусированным на непрерывности и идентичности жизненного цикла.Определите способ различения каждого объекта независимо от его формы или истории.Будьте внимательны к требованиям, которые требуют сопоставления объектов по атрибутам.Определите операцию, которая гарантированно даст уникальный результат для каждого объекта, возможно, добавив символ, который гарантированно уникален.Это средство идентификации может исходить извне или может быть произвольным идентификатором, созданным системой и для нее, но оно должно соответствовать различиям идентичности в модели.Модель должна определять, что значит быть одним и тем же.

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

Ответы [ 4 ]

2 голосов
/ 24 февраля 2012

Возможна пара подходов:

  • Используйте бизнес-ключ.Это наиболее подход «DDD-совместимый».Посмотрите внимательно на предметные и бизнес-требования.Как ваш бизнес идентифицирует клиентов, например?Используют ли они номер социального страхования или номер телефона?Как бы ваш бизнес решил эту проблему, если бы он был на бумажном носителе (без компьютеров)?Если нет естественного бизнес-ключа, создайте суррогат.Выберите окончательный бизнес-ключ и используйте его в equals().В книге DDD есть раздел, посвященный этой конкретной проблеме.

  • Для случаев, когда нет естественного бизнес-ключа, вы можете сгенерировать UUID.Это также имело бы преимущество в распределенной системе, и в этом случае вам не нужно полагаться на централизованный (и потенциально недоступный) ресурс, такой как база данных, для создания нового идентификатора.

  • Существует такжевозможность просто положиться по умолчанию equals() для классов сущностей.Он сравнил бы две области памяти, и в большинстве случаев этого достаточно, потому что Единица работы (сеанс Hibernate) сохраняется для всех объектов (этот шаблон ORM называется Карта идентичности ).Это ненадежно, потому что оно сломается, если вы используете сущности, которые не ограничены областью действия одного сеанса Hibernate (мыслительные потоки, отдельные сущности и т. Д.)

Интересно, что "официальный" DDDВ примере используется очень облегченная среда, в которой каждый класс сущностей получен из интерфейса Entity с одним методом:

boolean sameIdentityAs(T other) 
// Entities compare by identity, not by attributes.
1 голос
/ 24 февраля 2012

Дан Person класс с атрибутами name, surname.Когда лицо в возрасте 21 года меняет свое имя, остается ли оно тем же лицом (равно дает true)?Если вы пишете равные основы для атрибутов, то это не будет один и тот же человек, поэтому, на мой взгляд, лучший подход - это проверить равенство сущностей на основе их бизнес-идентификатора (уникального и неизменного в течение всего жизненного цикла сущности).

1 голос
/ 24 февраля 2012

Если объект еще не является постоянным, то есть ли вред при сравнении двух объектов на основе их атрибутов?

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

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

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

0 голосов
/ 20 сентября 2014

Другим решением может быть использование поля UUID в вашей сущности.

В этом случае вы можете использовать UUID в качестве первичного ключа или просто для равных.

@Entity
public class YourEntity{ 

    @Id
    private String uuid = UUID.randomUUID().toString();

    // getter only...

}
...