HTML Diff
1 added 1 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>При разработке приложения часто возникают сложности с удобством доступа к вложенным данным. Например, сложно быстро извлечь последние комментарии к вопросам в Q&amp;A (Вопросы и Ответы), если комментарии вложены внутрь самих вопросов. В таком случае необходимо обойти все вопросы, собрать комментарии и отсортировать их по времени.</p>
1 <p>При разработке приложения часто возникают сложности с удобством доступа к вложенным данным. Например, сложно быстро извлечь последние комментарии к вопросам в Q&amp;A (Вопросы и Ответы), если комментарии вложены внутрь самих вопросов. В таком случае необходимо обойти все вопросы, собрать комментарии и отсортировать их по времени.</p>
2 <p>Возьмем для примера<a>Q&amp;A Хекслета</a>. У каждого вопроса есть количество лайков и комментарии, у которых в свою очередь тоже есть лайки. Эти данные можно представить так:</p>
2 <p>Возьмем для примера<a>Q&amp;A Хекслета</a>. У каждого вопроса есть количество лайков и комментарии, у которых в свою очередь тоже есть лайки. Эти данные можно представить так:</p>
3 <p>Иерархическое представление данных хорошо отражает их структуру. Сразу видно, что к чему относится. Данные удобно выводить и достаточно удобно изменять. Особенно если вывод на экране совпадает с их структурой, и данные между собой не пересекаются. Вопросы и Ответы Хекслета как раз такой пример. Каждый вопрос живет своей независимой жизнью (кое-какие зависимости есть, но они не касаются самих данных).</p>
3 <p>Иерархическое представление данных хорошо отражает их структуру. Сразу видно, что к чему относится. Данные удобно выводить и достаточно удобно изменять. Особенно если вывод на экране совпадает с их структурой, и данные между собой не пересекаются. Вопросы и Ответы Хекслета как раз такой пример. Каждый вопрос живет своей независимой жизнью (кое-какие зависимости есть, но они не касаются самих данных).</p>
4 <p>Однако, если данные связаны, то иерархическая структура усложняет сквозные выборки. Представьте себе, что надо выводить 10 последних комментариев. Как это сделать? Придется ходить по всем топикам, брать все комментарии, объединять и искать самые свежие.</p>
4 <p>Однако, если данные связаны, то иерархическая структура усложняет сквозные выборки. Представьте себе, что надо выводить 10 последних комментариев. Как это сделать? Придется ходить по всем топикам, брать все комментарии, объединять и искать самые свежие.</p>
5 <p>Тут стоит сказать, что большая часть нужных выборок должна делать на бекенде и отправляться клиенту в готовом виде. Если же нужно делать такие расчеты на клиенте, то к организации объекта состояния можно подойти с другой стороны.</p>
5 <p>Тут стоит сказать, что большая часть нужных выборок должна делать на бекенде и отправляться клиенту в готовом виде. Если же нужно делать такие расчеты на клиенте, то к организации объекта состояния можно подойти с другой стороны.</p>
6 <h2>Создание индексов</h2>
6 <h2>Создание индексов</h2>
7 <p>Один из способов выйти из этой ситуации - начать дублировать данные. Создавать дополнительные структуры, оптимизированные под конкретные задачи. И хотя, в общем, это не лишено смысла, все же ручной способ поддерживать эти структуры ничего хорошего не принесет. В тех же базах данных за формирование индексов отвечает сама база данных. Нам как программистам не надо об этом заботиться. А здесь придется внедрять дополнительную синхронизацию во все этапы: добавление, изменение и удаление.</p>
7 <p>Один из способов выйти из этой ситуации - начать дублировать данные. Создавать дополнительные структуры, оптимизированные под конкретные задачи. И хотя, в общем, это не лишено смысла, все же ручной способ поддерживать эти структуры ничего хорошего не принесет. В тех же базах данных за формирование индексов отвечает сама база данных. Нам как программистам не надо об этом заботиться. А здесь придется внедрять дополнительную синхронизацию во все этапы: добавление, изменение и удаление.</p>
8 <p>Ниже пример создания объекта, оптимизированного под лайкнутые посты конкретными пользователями. Выборка вопросов, которые лайкнул конкретный пользователь (user1), превращается в простую операцию извлечения данных из объекта по ключу.</p>
8 <p>Ниже пример создания объекта, оптимизированного под лайкнутые посты конкретными пользователями. Выборка вопросов, которые лайкнул конкретный пользователь (user1), превращается в простую операцию извлечения данных из объекта по ключу.</p>
9 <p>Но тут возникает новая проблема: синхронизация данных. При изменении лайков (например, пользователь убрал лайк), нужно обновить оба объекта:</p>
9 <p>Но тут возникает новая проблема: синхронизация данных. При изменении лайков (например, пользователь убрал лайк), нужно обновить оба объекта:</p>
10 <p>Эти действия нужно выполнять при каждом изменении (добавление, удаление, изменение), и это легко приводит к ошибкам и рассогласованности данных.</p>
10 <p>Эти действия нужно выполнять при каждом изменении (добавление, удаление, изменение), и это легко приводит к ошибкам и рассогласованности данных.</p>
11 <p>Именно поэтому клиентское приложение редко занимается такими вещами вручную. Подобные структуры (индексы) автоматически создаются и поддерживаются на бэкенде или с помощью специальных библиотек управления состоянием. А сейчас активно развиваются полноценные клиентские базы данных, которые умеют с этим работать.</p>
11 <p>Именно поэтому клиентское приложение редко занимается такими вещами вручную. Подобные структуры (индексы) автоматически создаются и поддерживаются на бэкенде или с помощью специальных библиотек управления состоянием. А сейчас активно развиваются полноценные клиентские базы данных, которые умеют с этим работать.</p>
12 <h2>Нормализация данных</h2>
12 <h2>Нормализация данных</h2>
13 <p>Другой способ - нормализовать данные, прямо как в реляционных базах данных. Представить их плоскими массивами. Например, так:</p>
13 <p>Другой способ - нормализовать данные, прямо как в реляционных базах данных. Представить их плоскими массивами. Например, так:</p>
14 <p>Нормализованные данные существенно упрощают выполнение разнообразных выборок. Например, получение последних комментариев ко всем постам теперь выглядит проще и быстрее:</p>
14 <p>Нормализованные данные существенно упрощают выполнение разнообразных выборок. Например, получение последних комментариев ко всем постам теперь выглядит проще и быстрее:</p>
15 <p>Также упрощается получение постов, лайкнутых конкретным пользователем:</p>
15 <p>Также упрощается получение постов, лайкнутых конкретным пользователем:</p>
16 <p>Нормализованные данные тоже требуют синхронизации, но в основном для удаления. В нашем примере удаление поста должно приводить к удалению комментариев и лайков.</p>
16 <p>Нормализованные данные тоже требуют синхронизации, но в основном для удаления. В нашем примере удаление поста должно приводить к удалению комментариев и лайков.</p>
17 <p>И нормализованные данные требуют чуть более сложного кода при простых запросах типа "все комментарии конкретного поста":</p>
17 <p>И нормализованные данные требуют чуть более сложного кода при простых запросах типа "все комментарии конкретного поста":</p>
18 - <p>Но в целом это небольшая цена за преимущества, которые вы получите: простоту поддержки, отсутствие дублировани и легкость масштабирования. Именно поэтому большинство современных фронтенд-фреймворков и библиотек управления состоянием рекомендуют использовать именно нормализованный подход к хранению данных.</p>
18 + <p>Но в целом это небольшая цена за преимущества, которые вы получите: простоту поддержки, отсутствие дублирования и легкость масштабирования. Именно поэтому большинство современных фронтенд-фреймворков и библиотек управления состоянием рекомендуют использовать именно нормализованный подход к хранению данных.</p>
19 <p>Что по производительности? Является это проблемой или нет - вопрос открытый. Как правило, нет. Фронтенд очень редко оперирует большими количествами, например, десятками и сотнями тысяч. Чаще всего размеры коллекций ограничиваются сотней элементов. Но если производительность важна, то для этого используют разнообразные механизмы от кеширования до использования полноценных баз данных.</p>
19 <p>Что по производительности? Является это проблемой или нет - вопрос открытый. Как правило, нет. Фронтенд очень редко оперирует большими количествами, например, десятками и сотнями тысяч. Чаще всего размеры коллекций ограничиваются сотней элементов. Но если производительность важна, то для этого используют разнообразные механизмы от кеширования до использования полноценных баз данных.</p>
20 <h2>Какой подход выбрать?</h2>
20 <h2>Какой подход выбрать?</h2>
21 <p>Во многом ответ зависит от задачи и механизма управления состоянием. Как правило, в этих библиотеках есть документация, которая раскрывает как оптимальнее хранить данные внутри.</p>
21 <p>Во многом ответ зависит от задачи и механизма управления состоянием. Как правило, в этих библиотеках есть документация, которая раскрывает как оптимальнее хранить данные внутри.</p>
22 <p>Если же данные хранятся в обычных объектах без использования библиотек, то можно пойти следующим путем:</p>
22 <p>Если же данные хранятся в обычных объектах без использования библиотек, то можно пойти следующим путем:</p>
23 <ul><li>Для простоты всегда делать все плоским. Привыкнув к этому подходу, потом проще работать с любыми данными.</li>
23 <ul><li>Для простоты всегда делать все плоским. Привыкнув к этому подходу, потом проще работать с любыми данными.</li>
24 <li>Использовать вложенные структуры там где нет связи между данными и использовать плоские, там где нужно постоянно анализировать весь набор.</li>
24 <li>Использовать вложенные структуры там где нет связи между данными и использовать плоские, там где нужно постоянно анализировать весь набор.</li>
25 </ul><h2>Итог</h2>
25 </ul><h2>Итог</h2>
26 <p>Большинство фронтенд-приложений лучше всего работают с нормализованными данными, поскольку такой подход упрощает поддержку и масштабирование. Используйте иерархию только тогда, когда ваши данные полностью независимы друг от друга, и вы уверены, что это не изменится со временем.</p>
26 <p>Большинство фронтенд-приложений лучше всего работают с нормализованными данными, поскольку такой подход упрощает поддержку и масштабирование. Используйте иерархию только тогда, когда ваши данные полностью независимы друг от друга, и вы уверены, что это не изменится со временем.</p>