Насколько полезен / важен REST HATEOAS (уровень зрелости 3)?


110

Я участвую в проекте, где некоторые старшие члены команды считают, что REST API должен соответствовать требованиям HATEOAS и реализовывать все уровни зрелости Ричардсона ( http://martinfowler.com/articles/richardsonMaturityModel.html )!

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

Что вы думаете? Был ли у вас опыт работы с HATEOAS в реальном проекте?


Вот хорошая статья на эту тему: medium.com/@andreasreiser94/… В принципе, REST обычно реализуется, это RPC ...
masterxilo

Ответы:


214

Никто в сообществе REST не говорит, что REST - это просто. HATEOAS - лишь один из аспектов, который добавляет сложности архитектуре REST.

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

ОДНАКО миллиарды людей пользуются преимуществами REST сегодня. Вы знаете, что такое URL-адрес "кассы" на Amazon? Я не. Тем не менее, я могу оформлять заказ каждый день. Этот URL изменился? Я не знаю, мне все равно.

Вы знаете, все равно? Любой, кто написал скрин, очистил автоматизированный клиент Amazon. Кто-то, кто, вероятно, тщательно анализировал веб-трафик, читал HTML-страницы и т. Д., Чтобы узнать, какие ссылки вызывать, когда и с какой полезной нагрузкой.

И как только Amazon изменил свои внутренние процессы и структуру URL-адресов, эти жестко запрограммированные клиенты перестали работать - потому что ссылки оборвались.

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

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

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

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

У крупных сайтов с большой базой пользователей есть эта проблема. Они не могут просто попросить людей изменить их клиентский код по прихоти при взаимодействии с их системами. График разработки серверов не совпадает с графиком разработки клиента. Резкие изменения API просто неприемлемы для всех участников, так как они нарушают трафик и работу с обеих сторон.

Таким образом, такая операция, скорее всего, выиграет от HATEOAS, так как ее легче версировать, легче переносить старые клиенты, проще обеспечить обратную совместимость, чем нет.

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

Но большинству людей такая гибкость не нужна. Пишут серверный код для 2 или 3 отделов, это все для внутреннего использования. Если он сломается, они его исправят, и они учли это в своей обычной работе.

Гибкость, будь то REST или что-то еще, порождает сложность. Если вы хотите, чтобы это было просто и быстро, вы не делаете его гибким, вы просто делаете это и готово. По мере того, как вы добавляете абстракции и разыменование к системам, все становится сложнее, больше шаблонов, больше кода для тестирования.

Большая часть REST терпит неудачу из-за того, что "он вам не понадобится". Пока, конечно, не поймешь.

Если он вам нужен, то используйте его, и используйте его так, как написано. REST не пересылает информацию по HTTP. Этого никогда не было, это гораздо более высокий уровень, чем этот.

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


11
Я чувствую, что этот ответ должен получить как минимум на тысячу больше лайков. Честно говоря, я должен представить себе: насколько важно быть «настоящим» REST-вопрос, который возникает довольно часто. Черт, я искал в Google только по этой причине боеприпасы для использования на предстоящей встрече, когда я нашел эту ветку.
nograde

2
слава богу (или коду), кто-то говорит и о недостатках HATEOAS!
IlliakaillI

6
Есть ли еще какое-то преимущество, кроме возможности легко менять URL-адреса? Вы не можете просто добавлять новые опции, потому что, в отличие от людей, программа не может работать с чем-то новым. К тому же вы только перешли от построения знающих URL к знанию названия действий.
Джимми Т.

Если потребитель API ничего не знает, он может делегировать действия пользователя только 1: 1
Джимми Т.

2
Что касается изменения URL-адресов, не забывайте, что ваш клиент может использовать кеш, и поэтому вы должны сохранить поведение на сервере для обработки предыдущего URL-адреса (или просто выполнить перенаправление). Как и в случае любой другой стратегии развития API, вы должны сохранить прежнее поведение. HATEOAS здесь не особо помогает.
Бруно Коста

21

Да, у меня был некоторый опыт работы с гипермедиа в API. Вот некоторые из преимуществ:

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

  2. Встроенная документация: использование URL-адресов в качестве связей ссылок может указать разработчикам клиентов на документацию.

  3. Простая клиентская логика: клиент, который просто следует URL-адресам, а не создает их, должен быть проще в реализации и обслуживании.

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

  5. Разгрузка контента в другие службы: Hypermedia необходима при разгрузке контента на другие серверы (например, CDN).

  6. Управление версиями со ссылками: Hypermedia помогает управлять версиями API.

  7. Множественные реализации одной и той же службы / API. Гипермедиа необходима, когда существует несколько реализаций одной и той же службы / API. Например, сервис может быть API блога с ресурсами для добавления сообщений и комментариев. Если служба указана в терминах отношений ссылок, а не жестко закодированных URL-адресов, то одна и та же служба может быть создана несколько раз по разным URL-адресам, размещенным в разных компаниях, но все же доступной через один и тот же четко определенный набор ссылок одним клиентом.

Вы можете найти подробное объяснение этих пунктов здесь: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(здесь есть аналогичный вопрос: /software/149124/what-is-the-benefit-of-hypermedia-hateoas, где я дал такое же объяснение)


Несколько реализаций одного и того же сервиса: можете ли вы уточнить? Не понимаю, как это помогает.
Аббадон

Я попытался объяснить это в тексте. Помогает?
Jørn Wildt

11

Уровень зрелости Ричардсона 3 имеет ценность и должен быть принят. Йорн Вильдт уже суммировал некоторые преимущества, а другой ответ Уилта очень хорошо его дополняет.

Однако уровень зрелости Ричардсона 3 - это не то же самое, что HATEOAS Филдинга. Уровень зрелости Ричардсона 3 касается только дизайна API. HATEOAS Филдинга также касается проектирования API, но также предписывает, что клиентское программное обеспечение не должно предполагать, что ресурс имеет определенную структуру, выходящую за рамки структуры, определяемой типом носителя. Для этого требуется очень общий клиент, например веб-браузер, который не знает конкретных веб-сайтов. Поскольку Рой Филдинг ввел термин REST и установил HATEOAS в качестве требования для соответствия REST, возникает вопрос: хотим ли мы принять HATEOAS, и если нет, можем ли мы по-прежнему называть наш API RESTful или нет? Я думаю, что сможем. Позволь мне объяснить.

Предположим, мы достигли HATEOAS. Клиентская часть приложения теперь является очень общей, но, скорее всего, пользовательский опыт плох, потому что без каких-либо знаний семантики ресурсов представление ресурсов не может быть адаптировано для отражения этой семантики. Если ресурс «автомобиль» и ресурс «дом» имеют один и тот же тип носителя (например, application / json), то они будут представлены пользователю одинаково, например, в виде таблицы свойств (пары имя / значение).

Но ладно, наш API действительно RESTful.

Теперь предположим, что мы создаем второе клиентское приложение поверх этого API. Этот второй клиент нарушает идеи HATEOAS и имеет жестко закодированную информацию о ресурсах. Он по-разному отображает машину и дом.

Можно ли по-прежнему называть API RESTful? Я думаю так. API не виноват в том, что один из его клиентов нарушил HATEOAS.

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

Я включил раздел о HATEOAS в свой шаблон реализации REST под названием JAREST .


9

Мы создаем API уровня REST 3, где наш ответ находится в HAL-Json. HATEOAS отлично подходит как для внешнего, так и для внутреннего интерфейса, но он сопряжен с проблемами. Мы сделали некоторые настройки / дополнения для управления ACL внутри ответа HAL-Json (что не нарушает стандарт HAL-Json).

Я вижу самые большие преимущества HATEOAS в том, что нам не нужно писать / угадывать какие-либо URL-адреса в нашем интерфейсном приложении. Все, что вам нужно, это точка входа ( https://hostname), и оттуда вы можете просто просматривать ресурсы, используя ссылки или шаблонные ссылки, представленные в ответе. Подобно этому с управлением версиями можно легко справиться, переименовывая / заменяя URL-адреса, расширяя ресурсы дополнительными отношениями без нарушения кода интерфейса.

Кеширование ресурсов на интерфейсе - это несложно, используя ссылки на себя. Мы также отправляем ресурсы клиентам через соединение сокета, поскольку они также отображаются в HAL, мы могли бы легко добавить их в кеш таким же образом.

Еще одно преимущество использования HAL-Json заключается в том, что ясно, как должна выглядеть модель ответа, поскольку существует документированный стандарт, которому следует следовать.

Один из наших настроек является то , что мы добавили действия объекта внутри объекта собственной линии связи , который выставляет на переднем конце , какие действия или операции CRUD аутентифицированный пользователь может выполнять на соответствующем ресурсе ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE). Таким образом, наш интерфейсный ACL полностью продиктован нашим ответом REST API, полностью перекладывая эту ответственность на внутреннюю модель.

Итак, чтобы дать быстрый пример, у вас может быть объект сообщения в HAL-Json, который выглядит примерно так:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "john.doe@example.com",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

Теперь все, что нам нужно сделать во внешнем интерфейсе, - это AclServiceсоздать isAllowedметод, который проверяет, находится ли действие, которое мы хотим выполнить, в объекте действий.

В настоящее время на интерфейсе это выглядит очень просто: post.isAllowed('delete');

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

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


1
Очень хороший ответ. Я думаю, что именно такой практический пример и искал первоначальный вопрошающий.
www.admiraalit.nl

2

Я использовал HATEOAS в некоторых реальных проектах, но с другой интерпретацией, чем у Ричардсона. Если это то, чего хотят твои боссы, тогда, думаю, тебе стоит просто сделать это. Я считаю, что HATEOAS означает, что ваши ресурсы должны включать тип документа HTML, гиперссылки на связанные ресурсы и формы HTML, чтобы предоставлять функциональные возможности для глаголов, отличных от GET. (Это когда тип Accept - это text / html - другие типы контента не требуют этих дополнительных услуг.) Я не знаю, откуда пришло убеждение, что все ресурсы REST во всем вашем приложении должны быть склеены вместе. Сетевое приложение должно содержать несколько ресурсов, которые могут быть или не быть напрямую связаны. Или почему считается, что этому должны следовать XML, JSON и другие типы. (HATEOAS специфичен для HTML.)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.