Написание моего решения для автономного хранилища, часть 1. Вы не должны делать это так, как я.
Большая часть моего пути в качестве разработчика программного обеспечения заключалась в написании кода JavaScript, и я чувствую, что синдром NIH (Not Invented Here) намного сильнее проявляется в сообществе JS. Каждый день выходит новая библиотека для решения какой-либо задачи. Некоторые из них полезны, например https://www.npmjs.com/package/is-even.
Так что да, может быть, пока вы читаете эту статью, я пытался написать свой JQuery и свой CSS-фреймворк (и с треском провалился), но на самом деле я никогда не думал, что создам свой вроде Storage Engine. Спойлер: я этого не сделал — по крайней мере, не так, как должен был.
Этот пост открывает серию эссе о пути моей команды к внедрению автономного режима в приложении Ionic.
Изображение на обложке:https://www.blog.bixlabs.com/post/offline-first-mobile-apps
Оффлайн что ли?
Мне нравится определение в документации по Android.
Автономное приложение — это приложение, способное выполнять все основные функции или часть их основных функций без доступа к Интернету. То есть он может выполнять часть или всю свою бизнес-логику в автономном режиме.
Я работал над небольшим стартапом. У нас было замечательное приложение, которое помогает студентам в их повседневных занятиях. Приложение создает хорошее распределение на основе уровня знаний, к какому экзамену готовится студент и так далее.
Нам нужен был способ сделать так, чтобы пользователи могли учиться в автономном режиме, чтобы не отвлекаться на Tittok или что-то в этом роде. У нас были на то и другие деловые причины. Действительно, пользователи просили об этом, и мы делаем то, что хочет пользователь.
Где мы были
Как уже упоминалось, наше мобильное приложение было гибридным, написанным на Ionic. Бэкенд был написан на NodeJS, в основном это бессерверные функции с AWS Lambdas. Для базы данных мы использовали MongoDB.
Между нашим приложением и AWS per si существовал BaaS (бэкенд как услуга). Это обеспечило комбинацию между платформой Parse и AWS. Он предоставляет некоторые возможности, такие как аутентификация, хранение файлов, тип ORM и так далее. Вроде бы замечательно, но бесплатного обеда не бывает, это приносит некоторые проблемы, вроде меньшей гибкости.
В общем, вот как все было спроектировано.
Наше приложение было очень простым с точки зрения архитектуры, несмотря на то, что у нас был базовый код с большим количеством технических недостатков.
По характеристикам у нас было следующее:
- цикл — пользователи могли создавать свои учебные циклы;
- регистрация исследований — наши пользователи могли регистрировать свои исследования и иметь о них статистику;
- таймер для учебы — пользователь может запустить таймер для определенного предмета и может установить будильник, который будет оповещаться, когда время истекло.
У нас были и другие функции, но они имеют решающее значение для целей этой статьи.
Начните думать об оффлайне
Затем мы начали думать о нашей офлайн-реализации. Сначала это выглядело хорошо и просто. У нас был код TypeScript, который является просто надмножеством JavaScript, а JavaScript хорошо работает с JSON. И это то, что документ MongoDB является правильным? Это JSON.
Поначалу это предположение не кажется плохим, но по мере того, как мы углубляемся в наши решения, мы видим, что оно может привести ко многим проблемам (как это и произошло).
Сначала предполагалось, что большинство наших сущностей будут отключены. Самой важной из них является коллекция, которую мы можем назвать статистикой.У нас были и другие коллекции, но эта была далеко не решающей. Потому что эта коллекция должна была содержать информацию о том, сколько времени было потрачено на конкретную тему. Также какое исследование было проведено, включало ли оно тест, и на сколько вопросов мы ответили правильно в таком тесте и так далее.
Будучи молодым специалистом, я начал думать, что это будет хорошо для наших пользователей и не так уж сложно для реализации.
Вы когда-нибудь задумывались о реализации в автономном режиме? Ну, я могу вспомнить свои мысли по этому поводу. Я такой: «Круто, это просто вопрос сохранения данных на локальном устройстве, а потом, когда они подключатся, просто отправить их на сервер».
Мой план был:
- код только читает из локального хранилища (сделаем JSON.stringify в объектах);
- когда данные получены, обновить локальное хранилище;
- все записи сначала выполняются в локальном хранилище;
- отправить на сервер при наличии соединения.
Вы знаете, оглядываясь назад, это все еще кажется хорошим планом, потому что некоторые из этих идей я почерпнул из того, как Firebase делает для Cloud Firestore. Но в том-то и проблема, что это далеко не просто.
Основные вопросы по этому поводу: Синхронизация и Эффективность Local Storage. Мы будем говорить об этих проблемах в следующих постах, но позвольте мне обобщить их.
Эффективность локального хранилища
После обработки синхронизации это произошло. Нам не удалось измерить эффективность, и мы выбрали для этого плохие структуры данных. Когда мы работаем с мобильным устройством, может быть трудно предсказать, как будут вести себя разные устройства из-за различий в операционных системах и архитектурах устройств.
Проблемы, с которыми мы столкнулись:
- плохая производительность при поиске конкретных данных
- плохая производительность при поиске диапазона данных
- агрегированные расчеты
- сохранение данных в локальном хранилище
Синхронизация
Наш первый враг был сильнее. Нам нужно будет обработать синхронизацию, нам нужно будет ответить на эти вопросы:
- когда данные отправляются на сервер?
- откуда мы знаем, какие данные мы должны хранить? текущая или входящая? (конфликты)
- как обрабатывать удаления?
Краткое содержание
Мы были командой из ОДНОГО разработчика (мы были в процессе заключения контракта с еще одним), у нас не было хорошего технического руководства, и мы торопились (похоже, это путь стартапа). Итак, мы приняли много неверных решений, и я считаю, что самое серьезное из них — это не столько экспериментировать, сколько следовало бы.
Существует множество различных способов решения одной и той же проблемы. Надо было глубже вникать в подходы и сравнивать результаты.
Я не должен обвинять своих стейкхолдеров. В будущих постах вы увидите, что некоторые ошибки носят исключительно технический характер. Предполагается, что эта серия статей станет журналом плохих решений, и я надеюсь, что она будет полезна тем, кто сталкивается с подобными проблемами.
Вот и все. До встречи!