Предположим, у нас есть школы с некоторыми данными, включая имя и список студентов, а также студенты с некоторыми данными, включая курсы, в которые они записаны, и ссылки на их школу. На клиенте:Дизайн 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]
}
Мы всегда есть «полный» представления объектов со всеми их ссылки, так что это довольно легко Храните эту информацию в клиентской части хранилища данных. Однако для отображения каждого экрана потребуется несколько выборок. Чтобы показать информацию о студенте, нам нужно будет забрать студента, а затем забрать их школу, а также их курсы.
Есть ли более разумный подход, который позволил бы нам кэшировать только одну копию каждого объекта и предотвращать множественные выборки для отображения основных экранов?
Мне этот вопрос нравится, и найдите обсуждение [здесь] (http://programmers.stackexchange.com/questions/252362/is-it-a-good-idea-to-merge-multiple-http-requests- для-сберегающей полосы пропускания) полезно при обдумывании. В названии вашего вопроса упоминается кеширование, но тело этого не делает. Если вы используете второй (нормализованный) подход, ваш браузер может кэшировать сами запросы, сохраняя некоторые поездки на сервер. –
@ this-vidor Спасибо за ссылку! Я даже не рассматривал кеширование браузеров, просто держась за объекты («кеширование») в хранилище значений ключей в состоянии Redux. Я думаю, что использование кэша браузера и состояния Redux было бы частью реализации, которая не обязательно меняла бы ответ на исходный вопрос. –
Для этого я использую Redux и веб-браузер, но те же конструктивные ограничения могут легко применяться к любому другому клиенту (например, к родному приложению) с использованием другого хранилища данных на стороне клиента и некоторого другого HTTP-клиента с кешированием. –