Вопрос идентичности: объекты ценности

Отрывок из книги «Моделирование предметной области стало функциональным» — Скотт Влашин

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

В терминологии DDD объекты с постоянным идентификатором называются Entities, а объекты без постоянного идентификатора называются Value Objects. Давайте начнем с обсуждения объектов-значений.

Во многих случаях объекты данных, с которыми мы имеем дело, не имеют идентичности — они взаимозаменяемы. Например, один экземпляр WidgetCode со значением «W1234» совпадает с любым другим экземпляром WidgetCode со значением «W1234». Нам не нужно отслеживать, какой из них какой — они равны друг другу.

В F# мы можем продемонстрировать это следующим образом:

​ ​let​ widgetCode1 = WidgetCode ​"W1234"​
​ ​let​ widgetCode2 = WidgetCode ​"W1234"​
​ printfn ​"%b"​ (widgetCode1 = widgetCode2)  ​// prints "true"​

Понятие «значения без идентичности» часто встречается в модели предметной области, как для сложных, так и для простых типов. Например, тип записи PersonalName может иметь два поля — FirstName и LastName, поэтому он сложнее, чем простая строка; но это также и объект-значение, потому что два личных имени с одинаковыми полями взаимозаменяемы. Мы можем увидеть это в следующем коде F#:

​ ​let​ name1 = {FirstName=​"Alex"​; LastName=​"Adams"​}
​ ​let​ name2 = {FirstName=​"Alex"​; LastName=​"Adams"​}
​ printfn ​"%b"​ (name1 = name2)  ​// prints "true"​

Тип «адрес» также является объектом-значением. Если два значения имеют один и тот же адрес улицы, город и почтовый индекс, они являются одним и тем же адресом:

​ ​let​ address1 = {StreetAddress=​"123 Main St"​; City=​"New York"​; Zip=​"90001"​}
​ ​let​ address2 = {StreetAddress=​"123 Main St"​; City=​"New York"​; Zip=​"90001"​}
​ printfn ​"%b"​ (address1 = address2)  ​// prints "true"​

Вы можете сказать, что это объекты-значения в домене, потому что при их обсуждении вы бы сказали что-то вроде: «У Криса такое же имя, как у меня». То есть хоть мы с Крисом и разные люди, но имена у нас одинаковые. У них нет уникальной идентичности. Точно так же «У Пэт такой же почтовый адрес, как и у меня» означает, что мой адрес и адрес Пэт имеют одинаковое содержание и, следовательно, равны.

Реализация равенства для объектов-значений

Когда мы моделируем предметную область с помощью системы алгебраических типов F#, создаваемые нами типы будут по умолчанию реализовывать этот тип проверки на равенство на основе полей. Нам не нужно самим писать какой-то специальный код равенства, что приятно.

Чтобы быть точным, два значения записи (одного и того же типа) равны в F#, если все их поля равны, и два типа выбора равны, если они имеют один и тот же вариант выбора, и данные, связанные с этим вариантом, также равны. Это называется структурным равенством.

Надеемся, вам понравился этот отрывок. Вы можете продолжить чтение Моделирование предметной области стало функциональным на Medium.

Или купите электронную книгу прямо на The Pragmatic Bookshelf.

В рамках нашей Весенней распродажи 2023 года вы можете сэкономить 50 % на этой книге, используя код DATAFLOW2023 до полуночи по восточному времени 25 апреля 2023 года.

Чтобы получить печатную копию, посетите bookshop.org.