Keel:

Прошло уже какое-то время после внедрения - получали какой-нибудь фидбэк от девелоперов, использующих API?

Основной вопрос для меня сейчас в том, оправданно ли применение полноценного REST'а с гипертекстом, в ситуациях, когда девелоперы скорее всего не будут разрабатывать полноценный клиент, а когда им нужна какая-то одна конкретная фича.

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

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

Конечная идеализированная цель понятна :) но интересны и практические последствия :)

Я, к сожалению, не смогу ответить непосредственно на вопрос, потому что явного фидбека пока не много. Но вот прокомментировать некоторые вещи хочется.

Гипертекстовая природа

REST'овые API часто противопоставляются "простым", хотя на самом деле REST сам по себе особенной сложности не несёт. Да, сама концепция сложна для понимания, но если сравнивать код, реально работающий с REST API и не-REST API, то разницы в сложности особенной не будет.

Если я правильно понимаю, о чём идёт речь, то гипертекстовость REST — это наличие ссылок в представлениях ресурсов, которые ссылаются на другие ресурсы. Она обеспечивает такое свойство REST, как самоописываемость. И это хорошо. Но что гораздо лучше — это то, что она на самом деле не навязывается. Вы можете узнать ссылку на коллекцию постов текущего пользователя, прочитав предварительно ресрус /me/. Но вы не обязаны. Пара примеров:

Обратите внимание, что здесь "несколько GET'ов" (/me/ и последующий редирект на /person/{uid}/) делаются один раз при получении объекта. А set_status выливается, опять-таки, в один запрос.

Семантика медиатипов

Знание семантики медиатипов никак нельзя считать минусом. В абсолютно любом API надо знать форматы входных и выходных данных. Даже если это просто какой-нибудь "список строк", возвращаемых из функции, про это надо знать. REST всего лишь поощряет использование уже известных типов. Это а) экономит место в документации и б) позволяет использовать библиотеки.

Практический минус использования известных типов в том, что они могут быть сложны сами по себе. По сути правильно было бы сказать, что любой REST API настолько сложен, насколько сложны типы, которые он использует. В частности, мы использовали AtomPub для постов и комментариев. Это позволяет просто читать контент френд-ленты например с помощью Universal Feed Parser. Однако для полноценной работы никакая общая библиотека не поможет, потому что в формате есть Я.ру-специфичные данные. Именно поэтому мы принимаем также JSON-формат, помимо атомного XML с namespace'ами.

На практике я не вижу такой уж большой разницы в сложности текущего REST'ового кода:

urlopen(Request(
    BASEURL % '/person/17170120/post/',
    json.dumps({
        'content': 'New status',
        'access': 'public',
        'categories': [{'term': 'status', 'scheme': 'urn:ya.ru:posttypes'}],
    }),
    headers = {
        'Authorization': 'OAuth %s' % TOKEN,
        'Content-type': 'application/x-yaru-atom+json',
    },
))

… и гипотетического процедурного:

urlopen(Request(
    BASEURL % '/person/17170120/post/status/',
    urlencode({
        'value': 'New status',
        'access': 'public',
    }),
    headers = {
        'Authorization': 'OAuth %s' % TOKEN,
    },
))

Разница, конечно, есть. Например, в первом случае тип поста задаётся довольно дикой строчкой "categories", а во втором словом "status" в URL. Но это скорее показывает, что мы не очень хорошо выбрали JSON-формат, а не то, что это некая неотъемлемая сложность REST. Вполне могли бы обойтись и 'type': 'status' в контенте.

API Твиттера

API Твиттера не стоит противопоставлять REST. Он довольно много принципов оттуда использует:

Но в некоторых местах они от них отходят. Например, для POST'а твитов используется отдельный ресурс /statuses/update, хотя логичнее было бы принимать POST на общий ресурс статусов. Также отсутствие предгенерённых ссылок в ответах из API именно заставляет клиентов собирать URL'ы вручную. Не могу сказать, что эти отступления сильно усложняют дело, но и не упрощают тоже.

Комментарии: 2

  1. Keel

    Я не противопоставляю REST и Twitter API, просто Twitter API использует лишь подмножество REST и не использует гипертекст, а следовательно не совсем полноценный REST (http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven).

    Вы можете узнать ссылку на коллекцию постов текущего пользователя, прочитав предварительно ресрус /me/. Но вы не обязаны. Это так, но и REST API не обязано сохранять URI неизменными. В отличие от того же Twitter API, где URI - часть публичного "контракта".

    Про примеры. Это как раз один из тех моментов, которые и хотелось прояснить - делают ли люди полноценные клиенты, которые соблюдают "контракт" API или как обычно хардкодят.

    Судя по всему - в основном хардкодят. Но в этом и есть основной вопрос практической ценности именно гипертекста для подобных API.

    Если все равно будут брать и хардкодить - не лучше ли отказаться от гипертекста и просто вынести сами URI в публичное описание API, гарантируя тем самым, что ни один клиент не сломается однажды потому что API изменил URI.

  2. Ivan Sagalaev

    Я не противопоставляю REST и Twitter API, просто Twitter API использует лишь подмножество REST и не использует гипертекст, а следовательно не совсем полноценный REST

    "Полноценный" REST в смысле, описанном в диссертации Филдинга — вообще редкий зверь. Это набор принципов, и они не связаны настолько сильно, чтобы нельзя было от каких-то отказаться. Поэтому "REST" — это на практике всегда "REST в каких-то проявлениях".

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

    Судя по всему - в основном хардкодят. Но в этом и есть основной вопрос практической ценности именно гипертекста для подобных API.

    Если все равно будут брать и хардкодить - не лучше ли отказаться от гипертекста и просто вынести сами URI в публичное описание API

    Нет контракта о запрещении составления URL'ов. Есть лишь предложение готовых URL'ов, которые клиенту предлагается использовать. И клиент волен, опять-таки, делать и то, и то. Например, тот же pyyaru использует <link>и из выдачи, когда это удобно. Но думаю, что и захардкоженное там что-то есть.

    И к слову, у нас в документации правила составления URL'ов опубликованы. Правда, ими пользоваться не очень удобно местами: числовые идентификаторы в явном виде нигде не присутствуют.

Добавить комментарий