Как я должен иметь дело с иерархиями объектов в RESTful API?
в настоящее время я разрабатываю API для существующего приложения PHP, и с этой целью изучаю REST как разумный архитектурный подход.
Я считаю, что у меня есть разумное понимание ключевых концепций, но я изо всех сил пытаюсь найти кого-нибудь, кто занимался иерархией объектов и отдыхом.
вот в чем проблема...
в иерархии бизнес-объектов [application] мы имеем:
Users
L which have one-to-many Channel objects
L which have one-to-many Member objects
в самом приложении мы используем ленивый нагрузки подход к заполнению объекта пользователя массивами этих объектов по мере необходимости. Я считаю, что в терминах OO это агрегация объектов, но я видел различные несоответствия именования и не хочу начинать войну о точном соглашении об именовании .
теперь рассмотрим, что у меня есть некоторые слабо связанные объекты, которые я могу / не могу заполнить в зависимости от потребности приложения.
С точки зрения отдыха, я пытаюсь выяснить, какой подход должен быть. Вот мой текущий думая (учитывая получить только на данный момент):
Вариант 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 resources
Минусы: дальнейшее путешествие требуется для получения вторичных ресурсов
Вариант 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}
плюсы: первичные ресурсы предоставляют куда идти, чтобы получить субодинаты, но не то, что они (более спокойные?), нет необходимости получать подчиненных спереди, генераторы подчиненных списков (/каналы и / члены) предоставляют интерфейсы (метод, подобный), что делает ответ более похожим на службу.
Минусы: три вызова теперь требуется, чтобы полностью заполнить объект
Вариант 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 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/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
спецификация определяет несколько первичных представлений:
- "объект" (который представляет любой объект домена или услуги)
- список (ссылок на другие объекты)
- свойства
- коллекция
- действие
- результат действия (обычно содержащий либо объект, либо список, либо просто сообщения обратной связи)
- а также небольшое количество вторичных представлений, таких как home и user
Это интересно, поскольку вы увидите, что представления полностью самоописываются, открывая возможность реализации общих зрителей, если это необходимо.
кроме того, представления могут быть использованы непосредственно заказным приложением.
вот мои выводы из многочасового поиска и с вводом от ответчиков здесь:
там, где у меня есть объект, который фактически является многокомпонентным объектом, мне нужно рассматривать его как единый ресурс. Таким образом, если я получаю объект, все субординаты должны присутствовать. Это необходимо для того, чтобы ресурс был кэшируемым. Если я частично загружаю объект (и предоставляю штамп ETag), то другие запросчики могут получить частичный объект, когда они ожидали полного. вывод - объекты должны быть полностью заполнены, если они доступны в качестве ресурсов.
связанные отношения объектов должны быть доступны в виде ссылок на другие (первичные) ресурсы. Таким образом,объекты можно обнаружить, пройдя через API.
кроме того, иерархия объектов, которая имела смысл для основного сайта приложения, может оказаться не тем, что вам нужно действовать в спокойной манере, но, скорее всего, выявляет проблемы с существующая иерархия. При этом API может потребовать более специализированных вариантов использования, чем было предусмотрено ранее, и могут потребоваться специализированные ресурсы.
надеюсь, что это поможет кому-то