REST Медиа тип взрыва

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

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

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

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

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

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

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

application/vnd.mycompany.item_value+xml

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

Мои вопросы:

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

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

6 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

Чтобы люди понимали и использовали ваш API REST-ish, им необходимо понимать значение данных. Существуют API, в которых типы мультимедиа рассказывают большую часть истории; Например, если у вас есть API для преобразования текста в речь, тип носителя для ввода текста -text / plain, а тип носителя для вывода - audio / mp4, то, возможно, кто-то, знакомый с предметом, может обойтись. Текст в, аудио выход, вероятно, достаточно, чтобы продолжить в этом случае.

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

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

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

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

Вы используете тип носителя для передачи информации о ваших данных, которые должны храниться в самом представлении. Таким образом, вы можете иметь только один тип носителя, скажем, "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 на сервер.

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

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

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

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

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

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

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

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

В ответ на Даррел вот полный пост Роя. Разве вы не пытаетесь определить типизированные ресурсы, создавая свои собственные типы пантомимы?

Суреш, почему HTTP+POX не успокаивает?

Другие вопросы по тегам