” Объекты значений являются фундаментальным строительным блоком предметно-ориентированного проектирования, и они используются для моделирования концепций вашего вездесущего языка в коде.” Из книги Доменный дизайн на PHP — Карлос Буэносвинос, Кристиан Соронеллас, Кейван Акбари.
Введение
Эль-покровитель (más bien мини-покровитель), почему вы действительно хотите усилить использование в доменно-ориентированном дизайне (DDD). Шаблон Value Object усиливает иногда очень забытую концепцию принципов объектной ориентации, особенно теми, кто привык к слабо типизированным языкам://инкапсуляция .
Существуют различные определения того, что является Объектом ценности (ВО), что означает, что он существует Уорд Каннингем :
Примерами объектов значений являются такие вещи, как числа, даты, фильмы и строки. Обычно это небольшие предметы, которые используются довольно широко. Их идентичность основана на их состоянии, а не на идентичности объекта. Таким образом, у вас может быть несколько копий одного и того же объекта концептуальной ценности. Каждая банкнота в 5 долларов имеет свою собственную идентификацию (благодаря серийному номеру), но денежная экономия зависит от того, что каждая банкнота в 5 долларов имеет ту же стоимость, что и любая другая банкнота в 5 долларов.
Ла де Мартин Фаулер :
При программировании я часто нахожу полезным представлять вещи как составные части. 2D-координата состоит из значения x и значения y. Денежная сумма состоит из числа и валюты. Диапазон дат состоит из начальной и конечной дат, которые сами по себе могут состоять из года, месяца и дня.
(…) Объекты, которые равны по значению их свойств, в данном случае их координат x и y, называются объектами значений.
О ла-де-Карлос Буэносвинос, Кейван Акбари и Кристиан Соронеллас:
Объекты значений являются фундаментальным строительным блоком предметно-ориентированного проектирования, и они используются для моделирования концепций вашего вездесущего языка в коде.
В основном и другими словами: если мы сравним нашу систему с живым существом,//Value Object//будут равны клеткам | если мы сравним его со зданием, это будут кирпичи.
Value Object используется для моделирования концепций нашей системы, таких как идентификаторы, даты или диапазоны дат, цены, веса, скорости (практически любая величина моделируется как VO) или даже заголовки, имена или адреса. Объекты, например, состоят из Value Objects.
Характеристики
Существует ряд отличительных особенностей, которые делают класс есть рассмотрим Объект, Не Имеющий Ценности.
Измеряет, количественно или описывает концепцию
VO предназначены для измерения, количественной оценки или описания концепции нашего доменного уровня. Они не считаются |/что-то , но они являются ценностью, и как таковые имеют цель.
Непреложность
VO задуманы как неизменяемые объекты. Учитывая его ограниченный размер, его конструкция не оказывает сильного влияния на потребление памяти, поэтому создание нового экземпляра предпочтительнее, чем изменение уже существующего, тем самым избегая побочных эффектов, возникающих в результате их изменения.
Когда мы говорим о примитивах, мы можем присвоить значение одной переменной и сравнить ее с другой:
$a = 1; $b = 1; $a == $b; //true
Мы можем переназначить значение столько раз, сколько хотим, отбрасывая Предыдущее значение:
$a = 1; $a = 2; $a = 3; $a == 1; //false $a == 2; //false $a == 3; //true
И мы также можем изменить их с помощью операций, всегда получая новое значение:
$a = 1; $a = $a + 9; $a == 10; //true
Вместо этого, если мы передаем примитив в качестве аргумента функции, мы делаем это по значению (если мы явно не делаем это по ссылке) и функция не может изменить свое значение, если это не путем присвоения результата его переменной:
/\*\* Forma Incorrecta \*/
function add(int $a, int $b)
{
$a = $a + $b;
}
$a = 1;
$b = 9;
add($a, $b);
$a == 10; //false
/\*\* Forma correcta \*/
function add(int $a, int $b)
{
return $a + $b;
}
$a = 1;
$b = 9;
$a = add($a, $b);
$a == 10; //true
Идея состоит в том, что VO ведет себя так же, как базовый тип.
Всегда действителен
Конструктору VO всегда передаются примитивы (или другие VO), необходимые для создания экземпляра нового объекта, поэтому он всегда будет в допустимом состоянии, так как в случае отсутствия какого-либо значения или предоставления недопустимых значений он не будет построен и вызовет исключение.
Хорошая практика заключается в предоставлении статических семантических//конструкторов, которые облегчают создание VO, особенно когда один из параметров имеет ограниченный набор допустимых значений.
Они не обладают идентичностью
Никогда не путайте объект с value object. Основное различие заключается в том, что первые имеют идентификатор, идентификатор, который делает их уникальными перед другим экземпляром того же класса. Value object вместо этого не имеет идентичности, поэтому сравнения между value objects должны выполняться на основе их содержимого, а не идентификатора или ссылки.
Это довольно сильно сталкивается с поведением по умолчанию большинства языков программирования. Давайте посмотрим на следующий пример:
Как видно из первого примера, мы определили класс Point и создали два одинаковых экземпляра, но при выполнении метода equalsTo результат не такой, как ожидалось, поскольку проверка выполняется на основе ссылки на объект, а не на его содержимое.
Во втором случае сравнение возвращает ожидаемый результат, потому что мы сделали сравнение на основе содержимого объекта.
Инкапсуляция
Предположим, у нас есть класс Product, который среди прочего содержит атрибуты amount и currency. Учитывая эту схему, мы должны были бы отдельно предоставить два параметра,и если потребуется проверка currency, чтобы узнать, действительна ли она или поддерживается нашей системой, где бы мы ее поместили? В классе Product, похоже, не имеет большого смысла, и, кроме того, он нарушает принцип единственной ответственности . Кроме того, похоже, что эта проверка будет повторно использоваться много раз, а не только в контексте продукта.
Если мы создадим Vo Price, которая позволит нам инкапсулировать количество и валюту, а также выполнить все необходимые проверки во время его строительства, мы упростим проверки и повторное использование их, а также эффективно инкапсулируя атрибуты, которые индивидуально не имеют смысла сами по себе в контексте их использования.
Тестирование объектов обесценения
Совершенно очевидно, что тестирование этих небольших объектов является довольно простой задачей, поскольку у них практически нет логики за пределами проверок в их конструкторах, но давайте не будем забывать, что Value Object/| должны |/быть неизменными, и во время нашего тестирования мы должны убедиться, что это так, проверяя, что нет side-effects при выполнении любой операции с ними.
Если, например, наш класс Temperature, представляющий температуру, имел метод increase (Temperature $temperature), мы должны были бы убедиться, что после вызова метода экземпляр он не был изменен, но вернул новый Vo Temperature с новым увеличенным значением.
Пример
Учитывая принципы, которые мы видели, ниже мы можем увидеть пример VO, представляющий скорость:
Как вы можете видеть:
- Он измеряет, количественно или описывает концепцию.
- Он неизменен.
- Предоставляет семантические конструкторы для вашего строительства.
- Он действителен в конструкции, так что вы всегда будете иметь действительное состояние.
- Он сравнивается по значению, а не по ссылке (не имеет идентичности).
- Инкапсулирует в класс два атрибута, которые сами по себе не имеют смысл
Вывод
Хотя сначала может показаться немного громоздким моделирование каждой концепции нашей системы как объекта, долгосрочные преимущества более чем очевидны как на уровне реализации и повторного использования кода, так и на уровне тестирования.
Это правда, что сопоставление с базой данных может быть более сложным с сущностями, состоящими из VO, но если мы используем ORMs на основе Data Mapper (например, Doctrine) задача намного упрощается, мы увидим это позже в другом посте.
Ссылки
- Доменно-ориентированный дизайн на PHP , пор Карлос Буэносвинос, Кристиан Соронеллас и Кейван Акбари
- Доменно-ориентированный дизайн: Преодоление сложностей в основе программного обеспечения пор Эрик Джей Эванс
- Внедрение предметно-ориентированного проектирования Пор Вон Вернон
- Доменно-ориентированный дизайн (Дистиллированный) Уменьшенная версия предыдущей книги.
Оригинал: “https://dev.to/mangelsnc/value-objects-1gd9”