В чём разница между DTO и POCO? Часть 1: DTO
Некоторые разработчики используют термины DTO и POCO как синонимы. Но правы ли они, и в чём разница между DTO и POCO?
DTO
Data Transfer Object - это объект, предназначенный для передачи данных. По определению DTO должен содержать только данные, без логики или поведения, т.е. не должен содержать методов. В C# DTO должен иметь только свойства, которые должны только получать и устанавливать данные, но не проверять их и не выполнять с ними других операций.
Что насчёт атрибутов и аннотаций данных?
Нет ничего необычного в добавлении метаданных в DTO, чтобы он поддерживал, например, проверку модели. Такие атрибуты не добавляют поведения самому DTO. Поведение находится вне объекта.
А как же модели представления, модели API и т.п.?
Термин DTO ничего не говорит о предполагаемом использовании объекта. Во многих архитектурах DTO могут выполнять несколько ролей. Например, в большинстве архитектур MVC с представлениями, которые поддерживают привязку к типу данных, DTO используются для передачи и привязки данных к представлению (модели представления). В идеале они не должны иметь никакого поведения, только данные, отформатированные так, как этого ожидает представление. Но не все модели представления являются DTO, поскольку в архитектурах MVVM модели обычно включают логику поведения. И даже в приложениях MVC иногда в модель представления добавляется логика, так что они больше не являются DTO.
По возможности называйте свои DTO в соответствии с их предполагаемым использованием. Имя FooDTO не указывает на то, как и где этот тип следует использовать в архитектуре приложения. Вместо этого отдавайте предпочтение именам, раскрывающим намерения, например FooViewModel.
Ниже приведен пример объекта DTO на C#:
public class ProductViewModel {
public int ProductId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal UnitPrice { get; set; }
}
Инкапсуляция и DTOИнкапсуляция - важный принцип ООП, но он не относится к DTO. Поскольку DTO не имеют операций или поведения и не должны иметь скрытого состояния, они не нуждаются в инкапсуляции. Не усложняйте себе жизнь, используя закрытые мутаторы или пытаясь заставить ваши DTO вести себя как неизменяемые объекты. DTO должны быть простыми в создании, написании и чтении, и поддерживать сериализацию без дополнительных усилий.
Поля или свойства
Вы можете использовать как поля, так и свойства, но некоторые платформы сериализации работают только со свойствами. Соглашение в C# предписывает использовать свойства, но, если вам больше нравятся поля или есть причина их использовать, ничто вам не мешает.
Неизменяемость и записи
Неизменяемость имеет много преимуществ при разработке ПО, а также может быть полезной функцией в DTO. Неизменяемые DTO были головной болью разработчиков из-за невозможности использовать инициализаторы для свойств только для чтения и ограниченной поддержки сериализаторами. Однако это может измениться с появлением C# 9 и записей. Кстати, вы можете встретить ещё одну аббревиатуру - Data Transfer Record, (DTR). Вот один из способов определить DTR в C# 9 (позиционное объявление):
public record ProductDTO(int Id, string Name, string Description);Кроме того, можно использовать init-свойства:
public record ProductDTOInit-свойства поддерживают инициализацию при создании, а дальше доступны только для чтения, сохраняя неизменяемость записи. Также записи поддерживают сериализацию даже при позиционном объявлении. Вам может потребоваться несколько подсказок для сериализатора, если вы создадите свой собственный конструктор. Записи набирают популярность с выходом C# 9 и .NET 5, поэтому думаю, что они всё чаще будут использоваться для DTR.
{
public int Id { get; init; }
public string Name { get; init; }
}
Продолжение следует…
Источник: https://ardalis.com/dto-or-poco/