И опять про системную архитектуру.... Хотя системная ли она?
Что такое HATEOAS?
Hypermedia as the Engine of Application State, дословно «гипермедиа как движок для состояния приложения».
Представим себе, что у вас есть набор действий, которые пользователь может совершить на UI - набор кнопок, переходов, реакций интерфейса. Фактически, их можно описать набором URI, включающего параметры запроса включенного в path (query params).
В архитектуре HATEOAS, клиент запрашивает запрашивает условный контент и получает обратно сам контент и набор URI примерно в таком виде:
Другой вариант, более правильный, с которым нам помогает spring:
Последнее, относительно смыслов HATEOS, по пирамиде Ричардсона, HATEOS рассматривается как последний, наивысший уровень REST. Это же означает, что каждая ссылка подразумевает реализацию стандартных REST типов методов, таких как: PUT, GET, POST, PATCH, DELETE (и их подмножества). Это значит, что URI в links - это такой же набор ресурсов интерфейса.
Rel в примере выше - определение отношение сущности ответа к ресурсу по ссылке, где self - это ссылка на самого себя, могут быть и более сложные отношения, например для заказа, отношение доставки может выглядить так: order.delivery.
Отношения используются, как с точки зрения получения возможных действий, например вызов метода delet подразумевает попытку отмены ил удаления заявки. Get - получение информации.
Что дает использование HATEOAS:
- Навигацию по интерфейсу(API) на уровне спеки. Это однозначно повышает читаемость спецификации и дает представление о возможном реализации контракта провайдером на самом близком к реализации уровне.
- Возможность хранить контекст на UI без хранения контекста. Фактически, перестройка UI под ответ сервера, построение доступности и недоступности элементов управления и т.д. в совокупности с соблюдением рекомендаций по использованию метод REST дает возможность разгрузить серверную часть, при этом в большой степени, хотя это и не очевидно.
- Сконцентрировать управление пользовательскими сценариями на стороне back-end. Это не back-end driven-design, но интерфейс системы, в данном случае, строится от отношения сущностей в модели API back-end. И преодолеть это ограничение будет очень не просто.
- При интеграции back-to-back дает возможность сильно снизить coupling еще на этапе проектирования и получить очень элегантные API.
- HOTEOS идеально ложится в DDD-фреймворк. Особенно в паттерны реализации и управления сущностей, фабрик, расширяет возможности REST относительно ограничения контекстов..
Почему не стоит использовать HATEOS?
- Высокий порог входа и требовательность к проектированию. Гипермедиа-подход в проектирование REST-интерфейсов требует большого опыта в проектировании REST-интерфейсов. Учитывая мой опыт и тысячи разрабов и тех. лидов, которые прошли через мой ассесмент или собеседование. В проектирование просто REST-интерфейса могут процентов 40 из разрабов(senior/ senior+) на Java, Kotlin и Go (с другими дела не имел, к сожалению). А тут нужно четко понимать модель разделения функциональных опций между UI и back..
- Сильные границы и жесткие ограничения. Как писал Эванс в своей великой книге, чем жёстче фреймворк, тем болезненнее необходимость его нарушения. Если нам потребуется реализовать, что-то в HATEOS не укладывающееся, то все, что мы вокруг этого нового метода или API переделывать под этот метод или API, изменять тесты, скорее всего CD и молится, чтобы последствия этого эксепшена не протекли в остальные части проекта.
- Инструменты для тестирования сложны. Инструменты автоматического контрактного тестирования именно с особенностями HOTEOS пока работать не умеют, в полной мере. (если это не так, прошу пнуть меня в комментах), особенности реализации контрактного тестирования иерархических связанных API очень специфичны. Вот здесь про анти-паттерн "Волчий билет" , что случается, если вы не знаете или не хотите тестировать используемый фреймворк. Намекаю на важность и первостепенность тестирования данного подхода.
- Высокий риск безопасности. При неправильном проектировании и/или использовании API, возможен "взлом" пользовательского сценария.
Пример из реальной жизни: на одном сайте, предположим, предоставляющего некоторые государственные услуги на интерфейсе мне кнопка "Далее" была не доступна, а вот через окно отладки я смог продвинуться дальше по флоу оформления заграничного паспорта..
Хороший, если не идеальный, пример реализации HOTEOS - это gitlab
Возможна ли реализация HOTEOS без Contract-first.
Однозначно нет. Каким бы кунг-фу пандой не был разработчик, составить DTO в реализации, прокинуть его иерархию и не наследить с сущностями и фабриками у него вряд ли получится..
Итоги:
С одной стороны, HOTEOS дает великолепную возможность структурно строить системную архитектуру, снизить связанность(coupling), снизить lead-time и как следствие - ТТМ. Не в моменте, а вообще в масштабе времени.
Но при этом, он же накладывает существенные ограничения на инструменты и парадигмы проектирования и разработки, требователен к скиллам в области системной архитектуры, тестирования. Крайне тяжел к применению на этапах рефакторинга интерфейсов.