Ответ 1
TL;DR
Нет. DTO - всего лишь одно средство отделить модель домена на стороне сервера от представления, отображаемого в HTTP-ресурсах. Вы также можете использовать другие средства развязки, что и делает Spring Data REST.
Подробнее
Да, Spring Data REST проверяет модель домена, которую вы имеете на стороне сервера, чтобы понять, как будут выглядеть представления для ресурсов, которые она предоставляет. Однако он применяет пару принципиальных концепций, которые смягчают проблемы, которые принесет наивная экспозиция объектов домена.
Spring Data REST ищет агрегаты и по умолчанию формирует представления соответственно.
Основная проблема с наивным "Я бросаю свои объекты домена перед Джексоном" - это то, что из простой модели сущности очень трудно рассуждать о разумных границах представления. Особенно модели сущностей, полученные из таблиц базы данных, имеют привычку связывать практически все со всем. Это связано с тем, что важные концепции домена, такие как агрегаты, просто отсутствуют в большинстве технологий персистентности (читайте, особенно в реляционных базах данных).
Однако я бы сказал, что в этом случае "Не подвергайте свою модель домена" больше влияет на симптомы этого, чем на ядро проблемы. Если вы правильно спроектируете свою модель домена, существует огромное совпадение между тем, что выгодно в модели домена и как выглядит хорошее представление, чтобы эффективно управлять этой моделью с помощью изменений состояния. Несколько простых правил:
- Для каждого отношения к другому объекту спросите себя: не могло ли это быть ссылкой на идентификатор. Используя ссылку на объект, вы тянете много семантики другой стороны отношений в свою сущность. Как правило, это приводит к тому, что объекты ссылаются на объекты, относящиеся к объектам, что является проблемой на более глубоком уровне. На уровне представления это позволяет обрезать данные, диапазоны согласованности и т.д.
- Избегайте двунаправленных отношений, поскольку им, как известно, трудно добиться успеха на стороне обновления.
Spring Data REST делает довольно много вещей, чтобы фактически передать эти отношения сущностей в надлежащие механизмы на уровне HTTP: ссылки в целом и, что более важно, ссылки на выделенные ресурсы, управляющие этими отношениями. Он делает это, проверяя репозитории, объявленные для сущностей, и в основном заменяет в противном случае необходимую инкрустацию связанного объекта ссылкой на ресурс ассоциации, который позволяет вам явно управлять этим отношением.
Этот подход обычно хорошо работает с гарантиями согласованности, описанными агрегатами DDD на уровне HTTP. PUT
запросы не охватывают несколько агрегатов по умолчанию, что хорошо, так как это подразумевает область согласованности ресурса, соответствующего концепциям вашего домена.
Нет смысла вводить пользователей в DTO, если этот DTO просто дублирует поля объекта домена.
Вы можете ввести столько DTO для ваших объектов домена, сколько хотите. В большинстве случаев поля, захваченные объектом домена, каким-то образом отразятся в представлении. Мне еще предстоит увидеть объект Customer
, содержащий свойства firstname
, lastname
и emailAddress
, и те, которые совершенно неактуальны в представлении.
Введение DTO не гарантирует развязки ни в коем случае. Я видел слишком много проектов, где они, когда они были представлены по причинам, связанным с грузом, просто дублировали все области поддержки, которые им поддерживали, и тем самым вызвали дополнительные усилия, потому что каждая новая область также должна была быть добавлена в DTO. Но эй, развязывай! Не. ¯\_ (ツ) _/¯
Тем не менее, есть ситуации, когда вы хотите слегка настроить представление этих свойств, особенно если вы используете сильно типизированные объекты значений, например. a emailAddress
(хорошо!), но все же хотите сделать это как обычный String
в JSON. Но ни в коем случае не проблема: Spring Data REST использует Jackson под обложками, который предлагает вам широкий спектр средств для настройки представления - аннотации, mixins для сохранения аннотаций вне ваших типов доменов, пользовательских сериализаторов и т.д. представляет собой слой отображения между ними.
Не использовать DTO по умолчанию - это не плохая вещь сама по себе. Представьте себе протест пользователей о количестве необходимого шаблона, если мы хотим, чтобы DTO были написаны для всего! DTO - это всего лишь одно средство для достижения цели. Если эта цель может быть достигнута по-другому (и это обычно может), зачем настаивать на DTO?
Просто не используйте Spring Data REST, если он не соответствует вашим требованиям.
Продолжая усилия по настройке, стоит отметить, что Data REST существует, чтобы охватить именно те части API, которые просто следуют основным образцам реализации REST API, которые он реализует. И эта функциональность на месте, чтобы дать вам больше времени, чтобы подумать о
- Как сформировать модель вашего домена.
- Какие части вашего API лучше выражаются через взаимодействия с помощью гипермедиа.
Вот слайд из разговора, который я дал на SpringOne Platform 2016, в котором резюмируется ситуация.
Полную панель слайдов можно найти здесь. Там также есть запись беседы, доступная в InfoQ.
Spring Data REST существует для того, чтобы вы могли сосредоточиться на подчеркнутых кругах. Ни в коем случае мы не думаем, что вы можете создать отличный API только путем переключения Spring Data REST. Мы просто хотим уменьшить количество шаблонов, чтобы у вас было больше времени, чтобы подумать о интересных битах.
Так же, как Spring Данные в целом уменьшают количество кода шаблона, которое должно быть записано для стандартных операций сохранения. Никто не будет спорить, что вы можете создать приложение реального мира только из операций CRUD. Но, беря усилия из скучных бит, мы позволяем вам более интенсивно думать о реальных проблемах с доменом (и вы должны это сделать:)).
Вы можете быть очень избирательным в переопределении определенных ресурсов, чтобы полностью контролировать их поведение, в том числе вручную сопоставляя типы доменов с DTO, если хотите. Вы также можете разместить пользовательскую функциональность рядом с тем, что Spring Data REST обеспечивает, и просто подключить их вместе. Будьте избирательны в отношении того, что вы используете.
Образец
Вы можете найти немного расширенный пример того, что я описал в Spring RESTBucks, на основе Spring (Data REST) пример RESTBucks в книге RESTful Web Services. Он использует Spring Data REST для управления экземплярами Order
, но изменяет его обработку, чтобы ввести пользовательские требования и полностью реализовать платежную часть истории вручную.