В настоящее время я создаю REST-API для проекта и читаю статью за статьей о лучших практиках. Многие, кажется, против DTO и просто выставляют модель предметной области, в то время как другие, кажется, думают, что DTO (или пользовательские модели или как вы хотите это называть) - плохая практика. Лично я думал, что эта статья имеет большой смысл.
Однако я также понимаю недостатки DTO со всем дополнительным кодом отображения, модели доменов, которые могут быть на 100% идентичны их DTO-аналогам, и так далее.
Наш API в основном создан для того, чтобы другие клиенты могли использовать данные, однако, если мы сделаем это правильно, мы также хотели бы использовать их для нашего собственного веб-интерфейса, если это возможно.
Дело в том, что мы можем не захотеть предоставлять все данные домена другим пользователям клиента. Большая часть данных будет иметь смысл только в нашем собственном веб-приложении. Кроме того, мы можем не захотеть раскрывать все данные об объекте во всех сценариях, особенно об отношениях с другими объектами и так далее. Например, если мы представляем список определенного объекта, мы не обязательно хотим раскрывать всю иерархию объектов; так что дочерние объекты не будут выставлены, но могут быть обнаружены через ссылки (hateoas).
Как мне решить эту проблему? Я думал об использовании миксов Джексона в наших моделях предметной области для управления тем, какие данные будут представлены в различных сценариях. Или мы должны просто использовать DTO полностью - даже учитывая его недостатки и противоречия?
Ответы:
Почему вы должны использовать DTO в вашем REST API
DTO расшифровывается как D ata T transfer O bject .
Этот шаблон был создан с очень четко определенной целью: передавать данные на удаленные интерфейсы , как веб-сервисы . Этот шаблон очень хорошо вписывается в REST API, а DTO дадут вам больше гибкости в долгосрочной перспективе.
Модели, представляющие область вашего приложения, и модели, представляющие данные, обрабатываемые вашим API, представляют (или, по крайней мере, должны представлять собой) разные проблемы и должны быть отделены друг от друга. Вы не хотите ломать свои клиенты API, когда добавляете, удаляете или переименовываете поле из модели предметной области приложения.
Пока ваш сервисный уровень работает над моделями домена / персистентности, ваши контроллеры API должны работать с другим набором моделей. Например, по мере развития моделей вашего домена / персистентности для поддержки новых бизнес-требований вы можете захотеть создать новые версии моделей API для поддержки этих изменений. Вы также можете отказаться от старых версий API по мере выпуска новых версий. И это вполне возможно достичь, когда вещи отделены.
Просто упомяну несколько преимуществ предоставления DTO вместо моделей постоянства:
Отсоедините модели персистентности от моделей API.
DTO могут быть адаптированы к вашим потребностям, и они хороши, когда вы выставляете только набор атрибутов ваших постоянных сущностей. Вам не понадобятся аннотации, такие как
@XmlTransient
и,@JsonIgnore
чтобы избежать сериализации некоторых атрибутов.Используя DTO, вы избежите адских аннотаций в ваших персистентных сущностях, то есть ваши персистентные сущности не будут раздуты аннотациями, не связанными с персистентностью.
Вы будете иметь полный контроль над атрибутами, которые вы получаете при создании или обновлении ресурса.
Если вы используете Swagger , вы можете использовать
@ApiModel
и@ApiModelProperty
аннотации для документирования ваших моделей API, не портя ваши персистентные сущности.Вы можете иметь разные DTO для каждой версии вашего API.
У вас будет больше гибкости при отображении отношений.
Вы можете иметь разные DTO для разных типов медиа.
Ваши DTO могут иметь список ссылок для HATEOAS . Такого рода вещи не следует добавлять к объектам персистентности. При использовании Spring HATEOAS вы можете расширить классы DTO
RepresentationModel
(ранее известные какResourceSupport
) или обернуть ихEntityModel
(ранее известные какResource<T>
).Работа с шаблоном кода
Вам не нужно будет привязывать ваши персистентные сущности к DTO и наоборот вручную . Есть много картографических фреймворков, которые вы можете использовать для этого. Например, посмотрите на MapStruct , который основан на аннотациях и работает как обработчик аннотаций Maven. Он хорошо работает как в CDI, так и в Spring-приложениях.
Вы можете также рассмотреть вопрос о Ломбках для создания геттеров, сеттеров,
equals()
,hashcode()
иtoString()
метод для вас.Связанный: чтобы дать лучшие имена вашим классам DTO, обратитесь к этому ответу .
источник
Когда ваш API общедоступен, и вы должны поддерживать несколько версий, вы должны использовать DTO.
С другой стороны, если это частный API и вы управляете клиентом и сервером, я склонен пропускать DTO и выставлять модель домена напрямую.
источник
Я склонен использовать DTO.
Мне не нравятся недостатки, но кажется, что другие варианты еще хуже:
Экспозиция объектов домена может привести к проблемам безопасности и утечке данных. Может показаться, что аннотации Джексона решают проблему, но слишком легко ошибиться и раскрыть данные, которые не следует раскрывать. При разработке класса DTO совершить такую ошибку гораздо сложнее.
С другой стороны, недостатки подхода DTO могут быть уменьшены с помощью таких вещей, как сопоставление объектов с объектами и Lombok для меньшего количества шаблонов.
источник
Как вы уже заявили, это явно вопрос, связанный с мнением. Я сам больше отношусь к подходу без DTO, просто из-за всего необходимого вам кода.
Это в основном верно для ответной стороны json / rest api. Я даже написал аддон Джексона, чтобы избежать написания многих представлений / фильтров json для этих случаев: https://github.com/Antibrumm/jackson-antpathfilter
С другой стороны, DTO - хорошая вещь на стороне ввода данных таких API. Работать напрямую с сущностями может быть довольно сложно, например, принимая во внимание двунаправленные отношения. Кроме того, вы действительно не хотите, чтобы вызывающая сторона изменяла атрибут «создатель», например. Таким образом, вам нужно будет запретить определенные поля при отображении таких запросов.
источник