Взрыв типа REST

В моей попытке переделать существующее приложение с использованием архитектурного стиля REST, я столкнулся с проблемой, которую я бы назвал "Mediatype Explosion". Тем не менее, я не уверен, что это действительно проблема или неотъемлемая польза REST. Чтобы объяснить, что я имею в виду, сделайте следующий пример

Одна крошечная часть нашего приложения выглядит так:

коллекторно-оф-collections- > коллекциям-оф-изделия- > элементов

i.e верхний уровень представляет собой набор коллекций, и каждая из этих коллекций снова представляет собой набор элементов.

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

application/vnd.mycompany.collection-of-collections+xml
application/vnd.mycompany.collection-of-items+xml
application/vnd.mycompany.item+xml

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

application/vnd.mycompany.item_value+xml

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

Мои вопросы:

  • Я делаю что-то не так, имея огромное количество типов медиа?
  • Что такое альтернативный метод проектирования, чтобы избежать этого взрыва типов носителей?

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

Ответ 1

Один из подходов, который уменьшил бы количество требуемых типов носителей, - это использовать тип носителя, определенный для хранения списков других типов медиа. Это можно использовать для всех ваших коллекций. Как правило, списки имеют тенденцию к последовательному поведению. Вы можете свернуть свой собственный vnd.mycompany.resourcelist или вы можете повторно использовать что-то вроде Коллекция Atom.

Что касается конкретных представлений ресурсов, таких как vnd.mycompany.item, то, что вы можете сделать, во многом зависит от характеристик вашего клиента. Это в браузере? вы можете скачать код? Является ли ваш клиент богатым пользовательским интерфейсом или он является клиентом обработки данных?

Если клиент собирается выполнять определенную обработку данных, вам в значительной степени нужно придерживаться точных типов носителей, и вы можете столкнуться с большим количеством из них. Но посмотрите на яркую сторону, у вас будет меньше медиа-типов, чем у вас будут пространства имен, если вы используете SOAP!

Помните, что медиа-тип - это ваш контракт, если вашему приложению необходимо определить множество контрактов с клиентом, то пусть будет так.

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

Ответ 2

Я думаю, что, наконец, получил разъяснение, которое я искал для вышеупомянутого вопроса из презентация Иана Робинсона и подумал, что я должен поделиться им здесь.

В последнее время я встретил выражение " тип носителя, помогающий настроить движок гипермедиа, схему структуры" в записи блога Джим Уэббер. Затем я нашел этот presentation Ян Робинсон из Thoughtworks, Эта презентация является одним из лучших, с которыми я столкнулся, что дает очень четкое представление о ролях и обязанностях типов медиа и языков схем (вся презентация - это удовольствие, и я настоятельно рекомендую для всех). Особенно посмотрите слайды под названием "Вы выбрали приложение /xml, вы bstrd". и "Пользовательские типы носителей". Ян ясно объясняет разные роли схем и типов медиа. Короче говоря, это мой отрыв от презентации Яна:

Описание типа носителя включает в себя модель обработки, которая идентифицирует элементы управления гипермедиа и определяет, какие методы применимы для ресурсов этого типа. Идентификация средств гипермедиа означает "Как мы идентифицируем ссылки?" в XHTML ссылки идентифицируются на основе тега, а RDF имеет другую семантику для одного и того же. Следующее, что типы носителей помогают определить, какие методы применимы для ресурсов данного типа медиа? Хорошим примером является спецификация ATOM (application/atom + xml), которая дает очень богатое описание элементов управления гиперссылками; они сообщают нам, как определяется элемент ссылки? и что мы можем ожидать, чтобы иметь возможность делать, когда мы разыскиваем URI, чтобы он действительно рассказывал о методах, которые мы можем ожидать, чтобы иметь возможность применить к ресурсу. Структурная информация о представлении ресурсов НЕ является частью или НЕ, содержащейся в описании типа носителя, но предоставляется как часть соответствующей схемы фактического представления, то есть спецификация типа носителя не обязательно будет диктовать что-либо о структуре представления.

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

Надеюсь, что это поможет.

Ответ 3

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

Чтобы люди понимали и использовали ваш REST-ish API, им необходимо понять значение значения данных. Существуют API, в которых типы средств массовой информации рассказывают большую часть истории; например если у вас есть API для преобразования текста в речь, тип входного носителя является текстовым/обычным, а тип выходного носителя - аудио /mp 4, тогда кто-то, знакомый с предметом, может, вероятно, сделать это. Текст в, аудиовыход, возможно, достаточно, чтобы продолжить в этом случае.

Но многие API не могут передавать большую часть своего значения с помощью только типа медиа. Скажем, у вас есть API, который обрабатывает авиабилеты. Входы и выходы будут в основном данными. Типы носителей ввода и вывода каждого API могут быть application/json или application/xml, поэтому тип носителя не передает много информации. Таким образом, вы можете посмотреть отдельные поля на входах и выходах. Может быть, есть поле под названием "цена". Это в долларах или копейках? USD или какой-либо другой валюты? Я не знаю, как пользователь ответил бы на эти вопросы без (а) очень описательных имен, таких как "price_pennies_in_usd" или (b) документации. Не говоря уже о соглашениях о формате. Номер учетной записи, предоставленный с тире или без тарелки, должен содержать буквы и т.д. Нет стандартных типов носителей, которые определяют эти проблемы.

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

Но он полностью отличается, когда клиент (или, фактически, разработчик/пользователь за клиентом) должен понимать семантику данных. ДАННЫЕ НЕ МЕДИА. Невозможно объяснить данные во всех смыслах и тонкости реального мира, кроме документирования. Это вариант использования данных.

Слишком академическое определение REST работает в случае использования СМИ. Он не работает и должен быть дополнен нечистыми, но полезными вещами, такими как документация, для других случаев использования.

Ответ 4

Используется тип носителя для передачи сведений о ваших данных, которые должны храниться в самом представлении. Таким образом, у вас может быть только один тип носителя, например "application/xml", а затем ваши представления XML выглядят следующим образом:

<collection-of-collections>
    <collection-of-items>
        <item>
        </item>
        <item>
        </item>
    </collection-of-items>
    <collection-of-items>
        <item>
        </item>
        <item>
        </item>
    </collection-of-items>
</collection-of-collections>

Если вы обеспокоены отправкой слишком большого количества данных, замените JSON для XML. Другой способ сэкономить на байтах, написанных и прочитанных, - использовать кодировку gzip, которая сокращает около 60-70%. Если у вас нет сверхвысоких рабочих характеристик, один из этих подходов должен хорошо работать для вас. (Для лучшей производительности вы можете использовать очень тонкие строки вручную или даже сбрасывать собственный бинарный протокол TCP/IP.)

Изменить. Одна из проблем заключается в следующем:

делая [представление] грубыми средствами, я закончу передачу ненужных данных по проводу, когда на самом деле клиенту нужно только прочитать или написать один атрибут элемента

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

Вам следует взять копию Richardson и Ruby RESTful Web Services, которая является действительно отличной книгой о том, как создавать веб-службы REST и объясняет вещи намного яснее, чем мог. Если вы работаете на Java, я настоятельно рекомендую RESTlet framework, который очень точно моделирует концепции REST. Рой Филдинг Дисциплина USC, определяющая принципы REST, также может быть полезна.

Ответ 5

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

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

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

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

Другими словами, такой язык, как xsd, позволяет вам вводить тип носителя для поддержки одного из нескольких корневых элементов. В приложении /vnd.acme.humanresources + xml нет ничего неправильного, описывающего XML-документ, который может принимать либо или как корневой элемент.

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

Ответ 6

Если вы не собираетесь регистрировать эти типы носителей, вы должны выбрать один из существующих типов mime вместо того, чтобы создавать свои собственные форматы. Как Джим упоминает application/xml или text/xml или application/json работает для большей части того, что передается в проекте REST.

В ответ на Darrel здесь Рой полный пост. Не пытаетесь ли вы определить типизированные ресурсы, создав свои собственные типы mime?

Суреш, почему не HTTP + POX Restful?