Должен ли хорошо известный бизнес-идентификатор объекта быть представлен специальным типом в DDD / OOP?

9

В практическом плане это означает использование пользовательского (неизменяемого) classнад stringили каким-либо другим примитивным типом.

Примеры:

  1. Издательство: Международный стандартный номер книги.
  2. Финансы: международный идентификационный номер ценных бумаг.

Преимущества:

  1. Может обеспечить формат идентификатора.
  2. Становится первоклассным представителем модели.

Недостатки:

  1. Добавляет постоянство трения (например, Entity Framework).
  2. Больше кода
логово
источник
Вы должны использовать пользовательский класс? Конечно. Вы должны использовать их в качестве идентификаторов? Абсолютно нет :) Идентификация с деловым смыслом может вызвать проблемы на этом пути.
Сонго
2
@ Сонго Для меня это аргумент, что идентификаторы должны иметь семантику значений , но примитивные типы - не единственные типы с семантикой значений, так что это не обязательно исключает классы imo. Не стесняйтесь размещать конкурирующий ответ, хотя, поскольку я забыл высказать это мнение.
Ixrec
1
Мой старый вопрос касался этой темы с другими мнениями: programmers.stackexchange.com/questions/281827/… Я занимался созданием типов и продолжаю это делать.
Зив

Ответы:

6

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

Чтобы класс идентификатора был полезным, я ожидал, что он будет выглядеть примерно так:

class ISIN {
    fromCUSIP()
    fromRawISINString()
    toString(ISIN::FormatType)
    getExchange()
    getCountryCode()
    getLastFourDigits()
    getWhateverCode()
    ...
}

Если вместо этого это выглядит больше так:

class ISIN {
    getString()
    setString()
}

Затем я полностью исключил бы класс, использовал бы регулярные строки везде и удостоверился, что я последовательно использую «isin» во всех соответствующих именах переменных.

Обратите внимание, что в некоторых языках добавление нового типа практически не имеет «дополнительной сложности» в типичных программах, и в этом случае вам будет предложено создать новый тип, даже если он вообще не имеет никакой функциональности. Но это не так для большинства традиционных языков ООП, таких как C ++.

Ixrec
источник
6

Я бы сказал, пойти на это. Я бы сказал, что преимущества в этом случае перевешивают недостатки. Дополнительный код, вероятно, будет довольно минимальным, и проблему с постоянством можно решить довольно легко, предоставив какой-то конвертер между вашим новым классом и типом, который ожидает база данных (я никогда не использовал Entity Framework, но я знаю, что это относительно безболезненно в Hibernate).

Одним из преимуществ, которые вы можете получить, определив свой собственный класс, является то, что компилятор может гарантировать, что любые методы, которым нужен ISBN или ISIN, будут знать во время компиляции, если вы попытаетесь передать неправильное значение. Также будет намного сложнее случайно перезаписать это поле в вашей сущности. Мы можем полностью избежать распространенных ошибок:

book.setAuthor(otherBook.getAuthorName());
book.setIsbn(otherBook.getAuthorName());
book.setPrice(otherBook.getPrice())

Если ISBN является классом, а не примитивным типом, то приведенный выше код даже не скомпилируется, что значительно сэкономит время на отладку.

Мэтт Уотсон
источник
1
сеттеры и геттеры? Это 1992?
Майлз Рут