Чем мне не нравится REST

Когда я познакомился с REST подходом к построению web-сервисов мне он показался достаточно интересным. К тому же, о том, насколько крут REST говорили практически все. Более глубокое знакомство убедило меня в том, что REST создает больше проблем, чем решает. Более того REST формирует опасное ощущение разрешенности многих стандартных проблем, связанных с разработкой web-приложений.
О них и пойдет речь:

1. Отсутствие типизации. REST не поддерживает ни динамической, ни статической типизации, что значительно усложняет интеграцию и тестирование этой интеграции. Нужно заботится не только о том, чтобы реальное и ожидаемое поведения систем совпадали, нужно проверять и то, что используемые модели данных поддерживаются. Теоретически спецификация WSDL 2.0 оперирует терминами REST и могла бы быть использована для поддержки типизации в REST сервисах. Однако, кроме всеми горячо любимого Axis2 и мертворожденного Apache Woden связка REST WSDL 2.0 никем не поддерживается.

2. Просто реализовать CRUD семантику, однако реализация любой другой логики взаимодействия вызывает значительные затруднения. Мой любимый пример пакетные запросы, которые жизненно необходимы в любом web-приложении. Попробуйте реализовать пакетное удаление в REST. Нет Вы попробуйте! Глагол DELETE не поддерживает тела запроса. Точнее спецификация HTTP не упоминает о наличии тела запроса у DELETE. Соответственно, разработчики библиотек реализовывали его поддержку по желанию. С GET ситуация еще лучше. Там тела запроса быть не может, таким образом о сложных структурированных запросах на чтение можно забыть. Любой пакетный запрос в конечном счете превращается в POST.

3. Неполная поддержка HTTP-методов (REST-глаголов) браузерами. Поскольку HTML4 и XHTML1 требовали обязательной поддержки только GET и POST большинство разработчиков браузеров и не заморачивались реализацией всех остальных методов. Соответственно, единственный гарантированный способ поддерживать другие глаголы добавление поля с именем глагола в POST запрос, что опять-таки нарушает логику REST.

4. Семантика глагола POST требует передачи всего содержимого изменяемого объекта. На первый взгляд это упрощает реализацию, но только до того момента, как размер объектов вдруг начинает превышать 4Кб и количество операций изменения превышает 100 запросов в секунду. После этого разработчик хватается за голову и начинает реализовывать дополнительные методы частичного редактирования. Что вновь нарушает логику REST. Возможное решение проблемы полного редактирования предлагает спецификация RFC5789 PATCH Method for HTTP. Она была разработана в 2010 году. Учитывая занятость разработчиков браузеров реализацией поддержки HTML5, вряд ли PATCH получит широкое распространение в ближайшее время. RFC5789 вводит еще один HTTP-метод, а значит еще один REST-глагол, область применения которого пересекается с POST, PUT и частично DELETE. Структура PATCH конструкций значительно более сложна и громоздка по сравнению с остальными HTTP-методами.

5. Моя любимая SOP-problem и ее решение JSONP. Эта пара привлекла мое внимание исключительно тем, что делает бессмысленным само название "REST". Для несведущих поясню, что REST расшифровывается как Representational state transfer. Основная идея REST отделение представления данных от способа передачи, что теоретически должно позволить клиенту и серверу без дополнительных накладных расходов согласовывать способ представления данных и его использовать. На практике JSONP является единственным приемлемым решением проблемы SOP. И будет таковым до тех пор, пока все браузеры полностью не реализуют HTML5 Security. Ну и еще лет пять после этого события. JSONP фактически ограничивает способ представления данных только одним JSON.

6. Обработка ошибок. Сторонникам REST нравится утверждать, что в HTTP уже встроен мощный механизм обработки ошибок status code. Да, да, статус-код вот она панацея. Однако, если присмотреться, какие именно статус-коды реально используются в web-приложениях? 
200, 301, 303, 304, 401, 403, 404, 405, 500
Кстати, почти все REST-фреймворки используют вместо 405 код 404. 
Для обработки прикладных ошибок, специфичных для бизнес-логики приложения, пригодны только два кода: 
  • 412 Precondition Failed использование в production mode крайне не рекомендуется, лучше что-то вернуть и уведомить администратора
  • 500 Internal Server Error — сигнал о том, что что-то пошло не так. 
Обучающие примеры, которые при вызове PUT /product/51 возвращают 404, в реальной жизни, как правило, не имеют смысла, поскольку клиентское приложение получает запись прежде, чем ее редактировать, а следовательно, уверено в ее наличии.
Опять же, REST хорошо справляется с простейшим случаем, а для более-менее расширенного варианта приходится реализовывать собственный маппинг исключений в JSON и разбирать его на стороне клиента. Это пришлось бы делать и без REST.

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

По сути, популярность среди разработчиков завоевал не REST, а фреймворки его реализующие, которые заодно решили массу распространенных проблем:
  • конвертации объектов серверного приложения в JSON/XML представление
  • разделение логики обработки запросов (на основе адресов и глаголов)
  • сокрытие деталей работы с HTTP упрощенный доступ к заголовкам и атрибутам запросов.
В качестве приемлемой альтернативы REST я бы привел реализацию Command Query Separation подхода поверх HTTP. При этом можно легко использовать REST-фрейморки (Jersey, Jackson, JAX-B). Не накладывая на себя добровольно дополнительных REST-ограничений и оставаясь хозяином положения хотите GET делайте его, хотите изменить данные на сервере нет ничего проще и все это без проблем.

В качестве дополнительного подтверждения всех приведенных выше аргументов отмечу, что большинство RESTful API гигантов IT-индустрии (Amazon, Facebook, eBay, Yahoo, Youtube) на поверку являются реализацией Command Query Separation. Единственным у кого хватило честности это признать стал Facebook