Как мне работать с объектными иерархиями в RESTful API? - PullRequest
68 голосов
/ 06 октября 2010

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Чтение объекта User и включение ссылок на списки подобъектов, т.е.

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

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

api.example.com/channel/{channel_id}

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

Вариант 4 - (пере) рассмотреть проектирование объекта для REST

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

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

Любые мысли по поводу вышеизложенного приветствуются.

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

Пол

Ответы [ 4 ]

39 голосов
/ 06 октября 2010

Нет причин не объединять их.

  • 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»: пользователю нужны как индексные страницы ({user_id}/channel_list), так и полные представления ({user_id}/channels).

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

25 голосов
/ 06 октября 2010

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

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

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

9 голосов
/ 01 февраля 2013

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

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

В соответствии со стандартом URI будут выглядеть следующим образом:

  • api.example.com / object / user / 31
  • api.example.com / object / user / 31 / properties / username
  • api.example.com / object / user / 31 / collection / channel
  • api.example.com / object / user / 31 / collection / 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

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

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

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

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

6 голосов
/ 11 октября 2010

Вот мои выводы из многих часов поиска и с учетом информации от респондентов:

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

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

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

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

...