RESTFful/Resource Oriented Design

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

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

Или, с другой стороны, если пользователь получает ученика, и он хочет школу, он должен сделать ПОЛУЧЕНИЕ на школьном ресурсе, а также, если он хочет всех классов, которые принимает ученик, он должен сделать GET на ресурсе классов?

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

Спасибо,

Нил Уолтерс

Ответы

Ответ 1

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

Как я вижу, справедливы следующие соотношения:

  • школы имеют ноль или более студентов.
  • В школах есть ноль или более классов
  • У студентов есть нулевые или более классы
  • классы имеют ноль или более студентов

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

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

Учитывая это, я думаю, вам нужна структура 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 = > список студентов (как ссылки, а не полные ресурсы), зачисленных в курс

Ответ 2

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

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

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

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

Ответ 3

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