Здесь, в Salesforce, большая часть нашего кода написана на языках объектно-ориентированного программирования (ООП), особенно на Java. Java очень гибкая; в больших проектах то, что заставляет ее работать (или не работать), сводится к использованию вами соглашений: общих шаблонов и практических правил, которые упрощают вашу программу и помогают другим инженерам легче понять ее.

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

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

Большинство объектов в современных приложениях представляют вещи с явной идентификацией. Допустим, вы работаете с почтовым приложением, и у вас есть записи, хранящиеся в базе данных для сообщений, которые вы составляете и отправляете. Пользователь может создать несколько «идентичных» сообщений электронной почты (то есть с одинаковой темой и телом), сохранить их и отправить. Но ваше приложение должно рассматривать их как две отдельные сущности; у них будут разные личности, представленные уникальными идентификаторами. Несмотря на то, что их состав точно такой же, эти два объекта по-прежнему рассматриваются как уникальные в нашей модели предметной области; они не равны, потому что у них разные идентификаторы. Эти идентификаторы не представляют описательной информации об объектах, к которым они привязаны; их единственная цель - показать, что они разные. Объект, равенство которого определяется его идентичностью (обычно выражаемой через искусственный идентификатор), не является объектом значения.

И наоборот, сущность, равенство которой полностью определяется содержащейся в ней информацией, является объектом значения. Подумайте о концепции книги с литературной точки зрения. Как вы отличите каждую отдельную работу? Обычно это делается путем оценки трех частей информации: автора, заголовка и содержания. Так что, если вы читаете «Вишневый сад» Антона Чехова, вам нужно получить только один экземпляр, и неважно, какой экземпляр вы получите; все они взаимозаменяемы, потому что интересующий вас объект определяется его значением (автор, заголовок, содержание). Физическое проявление - будь то копия в твердом переплете, мягкая обложка, фотокопия, PDF-файл и т. Д. - не имеет значения.

Другой распространенный пример объектов-значений - это деньги. Подумайте о предмете в интернет-магазине; его цена обычно состоит из двух компонентов: суммы (обычно представляемой целым числом с плавающей запятой, например 13,37) и типа валюты, обычно представляемого строкой (например, «$» или «руб.»). Поскольку валюта не является встроенным типом языка, имеет смысл представить ее с помощью объекта. Но точно так же, как вы никогда не создадите базу данных с записями для всех возможных комбинаций цены и валюты, нет никакого смысла пытаться навязать этим объектам искусственную идентификацию с помощью идентификатора или какой-либо подобной конструкции. Объект money определяется исключительно значениями, из которых он состоит; «13,37 доллара США» означает «13,37 доллара США», независимо от того, к чему оно применяется.

Сделаем еще один шаг вперед: в реальном мире деньги взаимозаменяемы. Для потребителя одна 50-долларовая купюра не отличается по стоимости от другой 50-долларовой купюры. В вашем приложении это означает, что цена продукта A и цена продукта B могут быть представлены одним и тем же объектом денежной стоимости, если они оба стоят одинаковой суммы. Это указывает на еще один факт об объектах значений: они неизменяемы. То есть вы не можете изменять значения в объекте значения после его создания. Если вам нужны другие значения, вы создаете новый объект. Неизменяемость дает вашей программе много преимуществ, потому что, когда что-то неизменяемо, легче рассуждать. (Не верите? Прочтите Эффективная Java Джошуа Блоха для более подробного объяснения.)

На практике существует несколько способов создания объектов-значений. Вы всегда можете сделать это с помощью оператора new, если знаете, какие значения вам нужны. В качестве альтернативы вы можете создать его, вызвав метод существующего объекта значения, если новые значения зависят от старых. В этом случае исходный объект значения должен оставаться неизменным (помните, он неизменен!). Вы должны использовать принцип «спрашивайте, не говорите»: попросите существующий объект создать для вас новый и позволить ему обрабатывать всю необходимую логику вместо того, чтобы обращаться к объекту, извлекать определенные фрагменты информации и использовать их, чтобы создать свой собственный объект.

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

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

Все еще не уверены в назначении ВО или их отличии от объектов идентичности? Посмотрите этот отличный подкаст Матиаса Верраеса и Константина Кудряшова.

Хотите глубже погрузиться в теорию озвучивания? Загляните на эту страницу википедии.

И помните об этих четырех основных свойствах объектов-значений:

  • Они неизменны
  • Они взаимозаменяемы
  • Следует использовать принцип «спрашивай, не говори».
  • Различие между ВО и объектами идентификации зависит от предметной области