Как я должен иметь дело с иерархиями объектов в RESTful API?

в настоящее время я разрабатываю API для существующего приложения PHP, и с этой целью исследую REST как разумный архитектурный подход.

Я считаю, что у меня есть разумное понимание ключевых понятий, но я изо всех сил пытаюсь найти кого-либо, кто занимался иерархией объектов и отдыхом.

вот в чем проблема...

в иерархии бизнес-объектов [application] мы имеем:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects

в самом приложении мы используем ленивый нагрузки подход к заполнению пользовательского объекта массивами этих объектов по мере необходимости. Я считаю, что в терминах OO это агрегация объектов, но я видел различные несоответствия именования и не хочу начинать войну за точное соглашение об именовании .

теперь рассмотрим, что у меня есть некоторые слабо связанные объекты, которые я могу / не могу заполнить в зависимости от необходимости приложения.

С точки зрения отдыха я пытаюсь определить, каким должен быть подход. Вот мое настоящее. думая (рассматривая GET только на данный момент):

Вариант 1 - полностью заполнить объекты:

GET api.example.com/user/{user_id}

прочитайте объект пользователя (ресурс) и верните объект пользователя со всеми возможными предварительно загруженными и закодированными объектами канала и члена (JSON или XML).

плюсы: уменьшите количество объектов, не требуется обход иерархий объектов
Минусы: объекты должны быть полностью заполнены (дорого)

Вариант 2-заполнить первичный объект и включают ссылки на другие ресурсы объекта:

GET api.example.com/user/{user_id}

прочитайте объект пользователя (ресурс)и верните заполненные данные пользователя объекта пользователя и два списка.

каждый список ссылается на соответствующий (sub) ресурс, т. е.

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}

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

плюсы: клиент может выбрать загрузите подчиненных или иначе, лучше разделение объектов как ресурсов REST
Минусы: дальнейшая поездка необходима для получения вторичных ресурсов

Вариант 3-включить рекурсивные извлечения

GET api.example.com/user/{user_id}

прочитайте объект пользователя и включите ссылки на списки подобъектов, т. е.

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

вызов /channels вернет список ресурсов канала в виде (как указано выше):

api.example.com/channel/{channel_id}

плюсы: первичные ресурсы expose куда идти, чтобы получить субодинаты, но не то, что они (более спокойные?), нет требования, чтобы получить подчиненных спереди, генераторы подчиненных списков (/каналы и / члены) предоставляют интерфейсы (например, метод), делая ответ более сервисным.
Минусы: теперь требуется три вызова, чтобы полностью заполнить объект

Вариант 4 - (re)рассмотрим конструкцию объекта для отдыха

Я повторно использую [существующую] иерархию объектов приложения и пытаюсь примените его к REST - или, возможно, более непосредственно, предоставьте ему интерфейс API.

возможно, иерархия объектов REST должна быть другой, или, возможно, новое мышление RESTful обнажает ограничения существующего дизайна объекта.

любые мысли по вышеуказанным приветствуется.

большое спасибо

Павел

4 ответов


нет причин не комбинировать их.

  • api.example.com/user/{user_id} – возврат представления пользователя
  • api.example.com/channel/{channel_id} - возврат представления канала
  • api.example.com/user/{user_id}/channels - возвращает список представлений каналов
  • api.example.com/user/{user_id}/channel_list – возвращает список идентификаторов каналов (или ссылки на их полные представления, используя ссылки выше)

когда вы сомневаетесь, подумайте о том, как вы будете отображать данные пользователю без проблем с "API": a пользователь хочет обе страницы индекса ({user_id}/channel_list) и панорамный вид ({user_id}/channels).

как только у вас это есть, просто поддержите JSON вместо (или в дополнение к) HTML в качестве формата представления, и у вас есть отдых.


лучший совет, который я могу дать, - попытаться не думать о вашем REST api как о ваших объектах. Создаваемые ресурсы должны поддерживать необходимые варианты использования. При необходимости можно создать ресурсы для всех трех вариантов:

api.example.com/completeuser/{id}
api.example.com/linkeduser/{id}
api.example.com/lightweightuser/{id}

очевидно, мои имена немного глупы, но на самом деле не имеет значения, как вы их называете. Идея заключается в том, что вы используете REST api для представления данных наиболее логичным образом для конкретного сценария использования. Если их несколько сценарии, при необходимости создайте несколько ресурсов. Мне нравится думать о моих ресурсах больше как о моделях пользовательского интерфейса, а не о бизнес-объектах.


Я бы порекомендовал Restful Obects который является стандартом для предоставления restful модели домена

идея объектов Restful заключается в предоставлении стандартного универсального интерфейса RESTful для объектных моделей домена, отображении представлений их структуры с помощью JSON и включении взаимодействия с экземплярами объектов домена с помощью HTTP GET, POST, PUT и DELETE.

согласно стандарту, URIs будет например:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections/channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

есть и другие ресурсы

  • api.example.com/services
  • api.example.com/domain-types

спецификация определяет несколько основных представлений:

  • object (который представляет любой объект или службу домена)
  • список (ссылок на другие объекты)
  • свойства
  • коллекция
  • действие
  • результат действия (обычно содержащий либо объект, либо список, либо просто сообщения обратной связи)
  • а также небольшое количество вторичных представлений, таких как home и user

Это интересно, поскольку вы увидите, что представления полностью самоописываются, открывая возможность общих зрителей, которые будут реализованы при необходимости.

кроме того, представления могут потребляться непосредственно заказным приложением.


вот мои выводы из многочасового поиска и с вводом от ответчиков здесь:

где у меня есть объект, который фактически является многокомпонентным объектом, мне нужно рассматривать его как один ресурс. Таким образом, если я получу объект, все координаты должны присутствовать. Это необходимо для того, чтобы ресурс был кэшируемым. Если я частично загружаю объект (и предоставляю штамп ETag), то другие запросчики могут получить частичный объект, когда они ожидали полного. вывод - объекты должны быть полностью заполнены, если они доступны в качестве ресурсов.

связанные связи объектов должны быть доступны в виде ссылок на другие (первичные) ресурсы. Таким образом,объекты обнаруживаются путем обхода API.

кроме того, иерархия объектов, которая имела смысл для основного сайта приложения, может показаться не тем, что вам нужно действовать в спокойной манере, но, скорее всего, выявляет проблемы с существующая иерархия. При этом API может потребовать более специализированных вариантов использования, чем было предусмотрено ранее, и могут потребоваться специализированные ресурсы.

надеюсь, что это поможет кому-то