Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

5 лет назад
Открыть в
День 1107. #ЗаметкиНаПолях DateTime как Объект-Значение Объекты-значения являются ключевой частью предметно-ориентированного проектирования (DDD) и моделей предметной области. Однако разработчики используют их не так часто, как следовало бы, и часто неправильно их понимают. Тип DateTime в .NET является полезным примером объекта-значения. Объект-значение — это неизменяемый тип, экземпляры которого можно отличить только по значению их свойств. Любые два объекта-значения с одинаковыми свойствами можно считать равными. При моделировании системы многие разработчики задаются вопросом, когда использовать объект-значение, когда использовать сущность и как их объединить. Часто задуманный изначально объект-значение далее ведёт себя как сущность. Разработчики спрашивают что-то вроде: «Могу ли я иметь список объектов-значений в моей модели», - и ответ почти всегда - нет. Опять здесь может помочь DateTime. Имеет ли смысл иметь список объектов DateTime в модели? DateTime сам по себе, без контекста, не имеет значения в модели предметной области. Только когда он используется для описания чего-то (обычно Сущности) он становится полезным. Вот пример:
07.02.2022
08.02.2022
09.02.2022

Если вы обнаружите этот список в модели, что он значит? Нет способа это узнать. А вот так:
var article = new Article {
  CreationDate = new DateTime(2022,2,7),
  PublicationDate = new DateTime(2022,2,8),
  LastModifiedDate = new DateTime(2022,2,9)
};

Те же три значения DateTime теперь имеют контекст, так как они используются для описания сущности статьи. Аналогичный вопрос возникает относительно адреса. Опять же, он сам по себе не имеет смысла. Он имеет значение только тогда, когда вы делаете его адресом клиента или адресом доставки. Почему важна неизменяемость? Все свойства объектов-значений должны быть доступны только для чтения. Но какой в этом смысл? Вы наверняка часто использовали тип DateTime в своих программах. А сколько раз вы проверяли день или месяц экземпляра DateTime на допустимое значение? Ни разу. Вам не нужно этого делать, потому что невозможно создать экземпляр DateTime в недопустимом состоянии, и экземпляры неизменяемы. Если вы попытаетесь создать DateTime с недопустимыми значениями, например, с месяцем 13, вы получите исключение ArgumentOutOfRangeException:
var someDate = new DateTime(2022,13,1);

А если вы попытаетесь изменить значение свойства, вы получите ошибку компиляции, т.к. оно доступно только для чтения:
someDate.Month = 13;

Есть и другие причины важности неизменяемости, но с точки зрения моделирования предметной области это самая важная. Вы обретаете уверенность в том, что эти значения верны, и устраняете массу повторяющегося кода, который в противном случае был бы необходим для подтверждения достоверности во многих местах. Так как же их изменить? Объекты-значения могут предоставлять методы, которые «кажутся» изменяющими их, но на самом деле создают новые экземпляры. Это относится как к DateTime, так и к String в .NET. AddDays(), ToLower() и т.п. возвращают новый экземпляр. Помните об этом при разработке собственных объектов-значений. Любые предоставляемые вами методы, которые будут манипулировать состоянием объекта, должны вместо этого возвращать новый экземпляр с обновлёнными значениями. Одним очевидным преимуществом этого подхода является то, что логика проверки в конструкторе объекта-значения гарантированно будет выполняться для каждого метода модификации без необходимости дублировать её где-либо ещё. Итого Хотя объекты-значения чаще всего обсуждаются в контексте DDD, есть примеры их использования в фреймворках, с которыми вы работаете каждый день. В .NET типы DateTimestring) являются примерами объектов-значений, и знание их особенностей может помочь при проектировании таких типов в ваших приложениях. Источник: ef='https://ardalis.com/datetime-as-a-value-object/'>https://ardalis.com/datetime-as-a-value-object/