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

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

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

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

Ответ 1

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

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

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

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

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

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

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

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

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

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

Итак, такая операция, скорее всего, выиграет от HATEOAS, так как это проще для версии, проще для более старых клиентов для миграции, проще быть обратно совместимой, чем нет.

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

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

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

Значительная часть REST терпит неудачу в том, что "вам не понадобится". Пока, конечно же, вы это делаете.

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

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

Ответ 2

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

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

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

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

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

  5. Отключение загрузки содержимого в другие службы. Гипермедиа необходима при разгрузке содержимого на другие серверы (например, CDN).

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

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

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

(здесь есть похожий вопрос: https://softwareengineering.stackexchange.com/questions/149124/what-is-the-benefit-of-hypermedia-hateoas, где я дал такое же объяснение)

Ответ 3

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

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

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

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

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

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

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

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

Ответ 4

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

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

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

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

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

Таким образом, чтобы привести быстрый пример, вы могли бы иметь объект post в HAL-Json, который выглядит примерно так:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "delete": "DELETE",
                "replace": "PUT",
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "[email protected]",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET",
                    }
                }
            }
        }
    },
    "subject": "Post subject"
    "body": "Post message body"
}

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

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

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

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

Ответ 5

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