RESTFful/ Ресурс-ориентированный дизайн

Предположим, у меня есть трехуровневая иерархия, состоящая из школы, студентов и классов.

Если я выставляю ученика в качестве ресурса, мой вопрос заключается в том, должен ли я всегда возвращать родительскую "школу" и "классы детей" вместе с этим учеником, или должен ли быть параметр parm, который пользователь включает для указания такового. Возможно, что-то вроде &deep=True?

Или, с другой стороны, если пользователь получает ученика и хочет получить школу, он должен выполнить GET на школьном ресурсе, а также, если он хочет получить все уроки, которые посещает ученик, он должен выполнить GET. на ресурсе классов?

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

Спасибо,

Нил Уолтерс

3 ответа

Решение

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

На мой взгляд, имеют место следующие отношения:

  • школы имеют ноль или более учеников
  • школы имеют ноль или более классов
  • студенты имеют ноль или более классов
  • классы имеют ноль или более учеников

(Вы также можете тривиально расширить их с учителями / инструкторами, если ваши требования включают такую ​​информацию.)

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

Учитывая это, я думаю, вы захотите, чтобы структура URL была примерно такой:

  • http://example.com/lms/schools => Список школ
  • http://example.com/lms/schools/{school} => информация об одной школе
  • http://example.com/lms/schools/{school}/students => список студентов
  • http://example.com/lms/schools/{school}/students/{student} => информация об одном ученике
  • http://example.com/lms/schools/{school}/students/{student}/courses => список курсов (в виде ссылок, а не полных ресурсов) студент зачислен в
  • http://example.com/lms/schools/{school}/courses => список курсов
  • http://example.com/lms/schools/{school}/courses/{course} => информация об одном курсе
  • http://example.com/lms/schools/{school}/courses/{course}/students => список студентов (в виде ссылок, а не полных ресурсов), зачисленных на курс

Если вы будете больше думать о дизайне ресурсов, как о дизайне пользовательского интерфейса, тогда проблема станет проще. Нет никаких причин, по которым вы не можете вернуть подмножество школьной информации в представлении ресурса "Ученик", а также вернуть ссылку на полное представление школьного ресурса, если пользователь захочет увидеть больше.

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

Я знаю, что есть много людей, которые пытаются рассматривать REST как DAL, но это те же люди, которые расстраиваются, когда узнают, что вы не можете выполнять транзакции через интерфейс RESTful.

Другими словами, разработайте свой API так же, как если бы вы разработали веб-сайт (но без каких-либо приятных вещей), а затем создайте клиента, который может сканировать сайт на предмет необходимой информации.

Я полагаю, что добавление параметров запроса для оптимизации доставки является разумным. Я мог бы сделать его еще более общим и использовать include=<relation>, Это может быть расширено для всех типов. Обратите внимание, что вы можете использовать несколько включений: .../student/<id>?include=school&include=student назначит список [school, student] к параметру include, Это также позволит использовать общую схему, которая может быть полезна и для других ресурсов.

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