REST API - DTO чи ні? [зачинено]


154

Зараз я створюю REST-API для проекту і читаю статтю за статтею про кращі практики. Багато хто, здається, проти DTO і просто виставляють доменну модель, тоді як інші вважають, що DTO (або Користувацькі моделі або все, що ви хочете назвати) є поганою практикою. Особисто я думав, що ця стаття має багато сенсу.

Однак я також розумію недоліки DTO з усім додатковим кодом відображення, моделями доменів, які можуть бути на 100% ідентичними їхнім DTO-аналогам тощо.

Наш API в основному створений для того, щоб інші клієнти могли споживати дані, однак, якщо ми це зробимо правильно, ми також хотіли б використовувати їх для власного веб-інтерфейсу, якщо це можливо.

Вся справа в тому, що ми можемо не хотіти відкривати всі дані домену іншим клієнтським користувачам. Значна частина даних матиме сенс лише у нашому власному веб-додатку. Крім того, ми можемо не хотіти розкривати всі дані про об'єкт у всіх сценаріях, особливо стосунки з іншими об'єктами тощо. Наприклад, якщо ми виставляємо список конкретного об'єкта, ми не обов'язково хотіли б розкрити всю ієрархію об'єктів; щоб діти об'єкта не піддавалися впливу, а могли бути виявлені через посилання (гетеоа).

Як я повинен вирішити цю проблему? Я думав про те, щоб використовувати комбінації Джексона на наших моделях домену, щоб контролювати, які дані будуть піддані різним сценаріям. Або ми повинні просто використовувати DTO до кінця - навіть враховуючи його недоліки та суперечки?


9
Не дивуйтеся, якщо це питання закриється. Це скоріше питання, засновані на обговоренні, що означає, що немає чіткої правильної відповіді. Запитайте різних людей, і ви отримаєте іншу відповідь.
Бен Терлі

2
Це посилання на статтю ( ibm.com/developerworks/community/blogs/barcia/entry/… ) порушено.
pinkpanther

7
@pinkpanther Це чудова стаття, і шкода, що її більше немає. Ось кешована версія веб-архіву .
кассіомолін

Відповіді:


251

Чому слід використовувати DTO у своєму REST API

DTO означає Д ата Т ransfer Про ▪ Таблиця .

Ця модель була створена з цілком чітко визначеною метою: передача даних у віддалені інтерфейси , як і веб-сервіси . Ця модель дуже добре вписується в API REST, і DTO надасть вам більше гнучкості в довгостроковій перспективі.

Моделі, що представляють домен вашої програми та моделі, що представляють дані, якими обробляється ваш API, є (або принаймні повинні бути) різними проблемами і повинні бути відокремлені одна від одної. Ви не хочете ламати клієнтів API, коли ви додаєте, видаляєте чи перейменовуєте поле з моделі домену програми.

Поки ваш рівень обслуговування працює над моделями домену / постійності, ваші контролери API повинні працювати над іншим набором моделей. По мірі того, як ваші доменні / наполегливі моделі розвиваються для підтримки нових бізнес-вимог, наприклад, ви можете створити нові версії моделей API для підтримки цих змін. Ви також можете знехтувати старі версії API, коли випускаються нові версії. І це цілком можливо досягти, коли речі розв’язуються.


Зазначимо лише кілька переваг викриття DTO замість стійкості моделей:

  • Розв’яжіть моделі стійкості від моделей API.

  • DTO можуть бути адаптовані до ваших потреб, і вони чудові, коли викриваєте лише набір атрибутів вашої стійкості. Вам не знадобляться примітки, такі як @XmlTransientі @JsonIgnoreщоб уникнути серіалізації деяких атрибутів.

  • Використовуючи DTO, ви уникнете пекельних анотацій у ваших стійких сутностях, тобто ваші особи, що зберігаються, не будуть розкриті анотаціями , що не пов’язані зі стійкістю.

  • Ви будете мати повний контроль над атрибутами, які ви отримуєте під час створення або оновлення ресурсу.

  • Якщо ви використовуєте Swagger , ви можете використовувати @ApiModelта @ApiModelPropertyпримітки для документування ваших моделей API, не збиваючи ваших завзятостей.

  • Для кожної версії API ви можете мати різні DTO.

  • Ви матимете більшу гнучкість при зіставленні відносин.

  • Ви можете мати різні DTO для різних типів носія.

  • Ваші DTO можуть мати список посилань для HATEOAS . Це та річ, яку не слід додавати до об'єктів стійкості. Використовуючи Spring HATEOAS , ви можете зробити свої класи DTO розширеними RepresentationModel(раніше відомими як ResourceSupport) або обгорнути їх EntityModel(раніше відомий як Resource<T>).

Справа з кодовим кодом

Вам не потрібно буде зіставити зберігання об'єктів в DTOS і навпаки ручної її закриттям . Існує багато карток карток, які ви можете використовувати для цього. Наприклад, подивіться на MapStruct , який базується на анотації та працює як Maven Annotation Processor. Він добре працює як у програмах CDI, так і у Spring.

Ви можете також розглянути питання про Ломбках для створення геттеров, сеттерів, equals(), hashcode()і toString()метод для вас.


Пов’язано: Щоб дати кращі імена класам DTO, зверніться до цієї відповіді .


2
Якби я пішов шляхом DTO, чи було б ви зіставити всі доменні об'єкти на DTO або лише ті, які не були б ідентичними? Крім того, як би ви вирішили проблему розкриття даних на основі різних сценаріїв / контекстів? Кілька DTO на об'єкт домену?
benbjo

6
@benbjo Це залежить від вас. Зазвичай я відображую лише найскладніші об'єкти до DTO, сутностей, яким я не хочу, щоб усі атрибути були відкриті, і об'єктів, що мають великі зв'язки. DTO надають мені можливість мати список посилань, які слід використовувати в HATEOAS. Це та річ, яку я не додав би до своїх об'єктів стійкості.
кассіомолін

2
@molin дякую за інформацію та пропозиції. Я обов'язково перевіряю MapStruct. На перший погляд, це дуже добре відповідає моїм потребам.
benbjo

6
Шановний доносець, чи могли б ви хоча б пояснити причину свого приходу?
кассіомолін

8
Існує також архітектурна причина використовувати DTO замість об'єктів домену в API REST. API REST не повинен змінюватися, щоб не зламати існуючих клієнтів. Якщо ви використовуєте модель домену безпосередньо в API, ви створюєте небажане з'єднання між API та моделлю домену. Відповідно до принципу проектування "Свободна муфта", договір на обслуговування не повинен бути щільно пов'язаний з логікою обслуговування або деталями реалізації.
Пауло Мерсон

25

Коли ваш API загальнодоступний і вам потрібно підтримувати кілька версій, вам потрібно погодитися з DTO.

З іншого боку, якщо це приватний API і ви керуєте як клієнтом, так і сервером, я схильний пропускати DTO і піддавати безпосередньо модель домену.


Я згоден з вами в останній частині, і я зазвичай роблю це, але це мій перший публічний API. Я розгляну, що ви говорите про використання DTO для публічної частини. Можливо, приватна та публічна частини API дійсно повинні бути окремими, навіть якщо "їжте власну собачу їжу" - хороший принцип.
benbjo

11

Я схильний використовувати DTO.

Мені не подобаються недоліки, але здається, що інші варіанти ще гірші:

Експозиція об’єктів домену може призвести до проблем із безпекою та витоку даних. Анотації Джексона можуть здатися вирішити проблему, але надто просто помилитися і викрити дані, які не повинні піддаватися впливу. При проектуванні класу DTO зробити таку помилку набагато складніше.

З іншого боку, недоліки підходу DTO можна зменшити за допомогою таких речей, як відображення об'єкта на об'єкт та Lombok за меншу кількість котлоагрегату.


9

Як ви вже заявляли самі, це явно питання, пов'язане з думкою. Я сам більше привертаю увагу до підходу без DTO, просто тому, що вам потрібен код котла.

В основному це стосується відповіді на api json / rest. Я навіть написав Джексона Аддона, щоб уникнути написання багатьох переглядів / фільтрів json для цих випадків: https://github.com/Antibrumm/jackson-antpathfilter

З іншого боку, DTO є хорошою справою на стороні введення запитів таких API. Робота безпосередньо над суб'єктами може бути досить важкою, наприклад, враховуючи двонаправлені відносини. Крім того, ви дійсно не хочете, щоб абонент змінив атрибут "Creator", наприклад. Тому вам потрібно буде заборонити певні поля під час відображення таких запитів.


2
Я погоджуюсь, що моє запитання дещо пов'язане з думкою (і не відштовхується), проте я також шукав поради, як вирішити свою проблему. Я буду брати багато у вашому адоні Джексона, проте ви вважаєте, що використовувати міксини для контролю над тим, які дані повинні бути викриті в різних сценаріях, добре що робити?
benbjo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.