2016-08-08 3 views
5

Предположим, у нас есть школы с некоторыми данными, включая имя и список студентов, а также студенты с некоторыми данными, включая курсы, в которые они записаны, и ссылки на их школу. На клиенте:Дизайн API: кеширование «частичных» вложенных объектов

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

Есть ли хороший способ сделать все это, или некоторые из ограничений должны быть отменены?

Первый подход будет иметь API, который делает что-то вроде этого:

GET /school/1 

{ 
    id: 1, 
    name: "Jefferson High", 
    students: [ 
     { 
      id: 1 
      name: "Joel Kim" 
     }, 
     { 
      id: 2, 
      name: "Chris Green" 
     } 
     ... 
    ] 
} 


GET /student/1 

{ 
    id: 1, 
    name: "Joel Kim", 
    school: { 
     id: 1, 
     name: "Jefferson High" 
    } 
    courses: [ 
     { 
      id: 3 
      name: "Algebra 1" 
     }, 
     { 
      id: 5, 
      name: "World History" 
     } 
     ... 
    ] 
} 

Преимущество этого подхода заключается в том, что для каждого экрана, мы можем просто сделать один выборки. На стороне клиента мы могли бы нормализовать школы и студентов, чтобы они ссылались друг на друга с идентификаторами, а затем сохраняли объекты в разных хранилищах данных. Однако объект student, вложенный внутри school, не является полным объектом - он не включает вложенные курсы или ссылку обратно в школу. Аналогично, объект school внутри student не имеет списка всех участвующих учеников. Сохранение частичных представлений объектов в хранилищах данных приведет к созданию сложной логики на стороне клиента.

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

Другой подход может быть спроектировать API только вернуть идентификаторы вложенных объектов:

GET /school/1 

{ 
    id: 1, 
    name: "Jefferson High", 
    students: [1, 2] 
} 


GET /student/1 

{ 
    id: 1, 
    name: "Joel Kim", 
    school: 1, 
    courses: [3, 5] 
} 

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

Есть ли более разумный подход, который позволил бы нам кэшировать только одну копию каждого объекта и предотвращать множественные выборки для отображения основных экранов?

+0

Мне этот вопрос нравится, и найдите обсуждение [здесь] (http://programmers.stackexchange.com/questions/252362/is-it-a-good-idea-to-merge-multiple-http-requests- для-сберегающей полосы пропускания) полезно при обдумывании. В названии вашего вопроса упоминается кеширование, но тело этого не делает. Если вы используете второй (нормализованный) подход, ваш браузер может кэшировать сами запросы, сохраняя некоторые поездки на сервер. –

+0

@ this-vidor Спасибо за ссылку! Я даже не рассматривал кеширование браузеров, просто держась за объекты («кеширование») в хранилище значений ключей в состоянии Redux. Я думаю, что использование кэша браузера и состояния Redux было бы частью реализации, которая не обязательно меняла бы ответ на исходный вопрос. –

+0

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

ответ

3

Возможно, вы смешиваете два понятия: Хранение и Изображения.Вы можете вернуть ненормированное представление (первый предложенный вами вариант) без, также сохраняя этот «частичный» объект в вашей базе данных.

Поэтому я предлагаю попробовать вернуть ненормированные представления, но их сохранение нормализуется (если вы используете реляционную БД).

Кроме того, предложение по улучшению: вы можете использовать правильные URI вместо идентификаторов в своих представлениях. Вероятно, вы хотите, чтобы клиенты знали «где», чтобы получить этот объект, поэтому проще просто предоставить URI. В противном случае клиенту необходимо выяснить, как создать URI из идентификатора, и обычно это заканчивается тем, что он жестко закодирован в клиенте, что нет в REST.

+0

Это кажется довольно разумным подходом ко мне. Итак, в этом примере, когда мы хотим показать школьное представление, которое мы выберем для школы и сохраним нормированную школу, не сохранив ни одного ученика (поскольку объекты-ученики просто «частично» включены в представление). Тем не менее, мы все равно будем использовать частичные ученики для заполнения списка учащихся в школьном представлении. Проблема, которую я вижу, состоит в том, что, если бы мы пересматривали это школьное представление, нам пришлось бы делать выборку снова, потому что школа была бы в хранилище данных, но ссылочных студентов не было бы. Любые мысли о том, как с этим справиться? –

+0

Браузер должен/должен кэшировать * полный * ответ для вас (если необходимые директивы управления кешем предоставляются сервером), так что вам не нужно об этом беспокоиться. Вы можете повторить запрос, и вы должны получить кешированный документ, или сервер может сделать условный 'GET', который вы все еще можете оптимизировать на стороне сервера. Вы создаете кеш с нуля на стороне клиента? –

+0

да, и, возможно, наивно так. Я храню каждый из этих объектов в хранилище значений ключей с помощью Redux (поэтому выборка школы 1 будет хранить объект в 'state.schools [1]'). Кажется, что кеширование браузера поможет больше здесь. Если бы я просто полагался на кеш, я не уверен, что в сохранении объектов в хранилище значений ключа (или даже при использовании Redux) будет какая-то проблема. –

 Смежные вопросы

  • Нет связанных вопросов^_^