Подтвердить что ты не робот

Проблематично ли, что Spring Data REST предоставляет объекты через ресурсы REST без использования DTO?

В моем ограниченном опыте мне неоднократно говорили, что вы не должны передавать объекты в интерфейс или через отдых, а вместо этого использовать DTO.

Не работает ли Spring Data Rest именно это? Я кратко рассмотрел прогнозы, но похоже, что они просто ограничивают возвращаемые данные и все еще ожидают, что объект как параметр для метода post для сохранения в базе данных. Я что-то упустил, или я (и мои коллеги) неверен в том, что вы никогда не должны проходить и сущность?

4b9b3361

Ответ 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, в котором резюмируется ситуация.

Что составляет REST API, построенный с помощью  Spring Data REST

Полную панель слайдов можно найти здесь. Там также есть запись беседы, доступная в 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, но изменяет его обработку, чтобы ввести пользовательские требования и полностью реализовать платежную часть истории вручную.

Ответ 2

Spring Data REST позволяет очень быстро прототипировать и создать REST API на основе структуры базы данных. Мы говорим о минутах против дней, когда сравниваем их с другими технологиями программирования.

Цена, которую вы платите за это, заключается в том, что ваш REST API тесно связан с вашей структурой базы данных. Иногда это большая проблема. Иногда это не так. Это зависит в основном от качества дизайна вашей базы данных и от возможности изменить ее в соответствии с потребностями пользователей API.

Вкратце, я рассматриваю Spring Data REST как инструмент, который может сэкономить вам много времени при определенных особых обстоятельствах. Не как серебряная пуля, которая может быть применена к любой проблеме.

Ответ 3

Мы использовали DTO, включая полностью традиционные слои (Database, DTO, Repository, Service, Controllers,...) для каждого объекта в наших проектах. Когда-нибудь Hopping DTOs спасет нашу жизнь:)

Итак, для простого объекта City, который имеет id,name,country,state, мы сделали следующее:

  • City таблица с столбцами id,name,county,....
  • CityDTO с id,name,county,.... свойствами (точно так же, как база данных)
  • CityRepository с findCity(id),....
  • CityService с findCity(id) { CityRepository.findCity(id) }
  • CityController с findCity(id) { ConvertToJson( CityService.findCity(id)) }

Слишком много кодовых таблиц, чтобы предоставить клиенту информацию о городе. Поскольку это простой объект, ни один бизнес не выполняется на всех этих слоях, просто объекты проходят мимо. Изменение в объекте City начиналось с базы данных и меняло все слои. (Например, добавив свойство location, так как в конце свойство location должно отображаться пользователем как json). Добавление метода findByNameAndCountryAllIgnoringCase требует изменения всех слоев (каждый слой должен иметь новый метод).

Учитывая Spring Data Rest (of course with Spring Data), это не просто!

public interface CityRepository extends CRUDRepository<City, Long> {
   City findByNameAndCountryAllIgnoringCase(String name, String country);
}

Объект City подвергается клиенту с минимальным кодом, и все же вы контролируете, как город открыт. Validation, Security, Object Mapping... все есть. Таким образом, вы можете настроить все.

Например, если я хочу, чтобы клиент не знал об изменении имени объекта City (разделение слоев), я могу использовать настраиваемый объект mapper, упомянутый https://docs.spring.io/spring-data/rest/docs/3.0.2.RELEASE/reference/html/#customizing-sdr.custom-jackson-deserialization

Подводя итоги

Мы используем как можно больше, в сложных случаях мы по-прежнему можем использовать традиционное разбиение на слои и Service и Controller делать некоторые дела.