Сразу скажу - я лишь поделился своим опытом и причиной выбора других решений без претензий к вашему подходу. И я только за, если будут альтернативные приложения с разными подходами, так как каждый выберет своё по душе.
Приложение делал в первую очередь для закрытия курсачей/диплома и для того, чтобы поиграться с архитектурой и технологиями. И в параллель этому чтобы сделать что-то полезное, а не для захвата всех ВУЗов)
Идея приложения - как идея moodle (система электронного образования, которую подключают себе вузы): предоставлять инструмент, которым могут воспользоваться. Android приложение moodle позволяет ввести url сайта, логин и пароль и не отвечает за контент каждого отдельного бэка. Оно просто даёт инструмент для её использования. Примерно с такой же идеей и решил делать приложение.
В целом ответы на вопросы ниже такие же, как и если бы эти вопросы были адресованы разрабам moodle.
Не кажется ли вам утопичной идея, что студенты всей страны (считаю, у ВУЗов такой заинтересованности нет совсем) решат поднимать аж бекенд для подключения собственного учебного заведения?
Вполне в ВУЗах может найтись хотя бы 1 такой энтузиаст бeкэндер. С ВУЗом можно договориться, чтобы поднять бэк у него (да, не всегда пойдут на встречу, но мне вполне подняли, когда попросил через научрука). И этот проект можно оформить как курсовую/диплом (который ещё могут оценивать не так строго, так как работа на пользу ВУЗа).
Идея приложения, чтобы бэки сами отвечали за себя (как и у moodle)
Что энтузиаст получает за внедрение своего ВУЗа в ваше приложение
Ничего, кроме хорошей темы для курсовой/диплома, фана и практики кодинга.
Что будете делать, если кому-то надоест хостить своё решение и у вас 1000 пользователей окажется без расписания? Что будете делать, если новый владелец хоста появится внезапно и будет вместо расписания добавлять что-то нехорошее?
Будут проблемы у конкретной бэка. Последствия такие же, если кто-то напишет своё приложение для ВУЗа со своим бэком, хотя в гугл плее такие тоже есть и нормально работают. Также, если конкретный бэк для moodle сломается.
В целом, как решаете возможные проблемы с рекламой, треш-контентом, etc. при получении данных с серверов, которые вам ничего не должны, и влияния вы на них не имеете?
Никак. Люди просто не будут пользоваться этим бэком.
Как решите вопрос, что расписание почему-то устаревшее, так как не получается напрямую с сервера?
Обращаться к конкретному бэку, чтобы он чаще обновлял его.
Как обойдёте сервисы вроде DDOS-Guard
С этой проблемой не встречался. Но опять же это на холдере бэка. Договориться с ВУЗом, возможно. Других вариантов в голову не приходит, так как не сталкивался с этим.
Кстати, а почему дока по контракту отсутствует
Частичная дока по контракту есть, но приложение в целом не очень доделано (описал это в первом комменте, что не осилил скоуп задачи и переделок, чтобы это пилить в параллель работы). Хотя планирую не делать ломающие изменения + добавить версионирование.
> Легче править ошибки в парсинге и обогащении данных
Чем легче то?
Тем что всё на бэке и для правки не нужно вносить изменение в приложение и всё сразу начнёт прилетать с бэка после фикса. Если делать локально, то нужно париться о каждом ВУЗе. И чем больше их - тем больше вероятность того, что нужно будет делать новый релиз. А это та ещё морока + время на ревью в разных сторах
А точно ли вам будет проще достучаться до владельца сервера, который выпустился из ВУЗа, у него появилась работа, жена, дети, и ему до этого сервера уже нет дела? В моём случае, небольшую правку, да даже полное переписывание парсера, можно внедрить самостоятельно - банально исходники парсера имеются, в отличие от.
Достукиваться и не планировал. В этом согласен - преимущество вашего подхода. Но сознательно выбирал именно подход moodle с его плюсами и минусами.
> Данные намного чище
Каво? А аргументы будут, или просто "у меня лучше, у меня контракт!!1"?
Тут пошла какая-то пассивная агрессия на нейтральный комментарий.
Мой ВУЗ предоставляет расписание только по группе. Для других сущностей расписание придётся через сложные способы вычислять. У некоторых ВУЗов могут быть данные ещё хуже. И чистота данных в плане того, что на бэке есть время скачивать кучу нужных данных у ВУЗа, обогащать и причёсывать данные. В случае локального парсинга - тут мы сильно ограничены, временем и нагрузкой на сервера ВУЗа (одно дело, когда один бэк выгружает кучу данных у ВУЗа, а другое дело, когда это будут делать тысячи студентов по несколько раз в день).
Часто студенты забывают, где учатся? Это достаточно важная информация, чтобы пользователю постоянно об этом напоминать?
Когда у тебя в ВУЗе куча кафедр, становится полезно/интересно знать, с какой кафедры препод или с какой кафедры/направления группа, с которой у вас общее занятие.
Очень интересно узнать, откуда у вас аватарки студентов, насколько обоюдно получаете их
Это просто ссылка на аватарку с лк ВУЗа. И для моего ВУЗа бэк запущен на сервере ВУЗа. Так что по сути всё хранится на серверах ВУЗа в любом из случаев)
А вы точно хотя бы скриншот в Google Play видели? Там всё, что выдаётся на обычном сайте, показывается пользователю. Да, весьма в удобном виде.
У меня цель отобразить полезную информацию, а не закошмарить кучей вспомогательной. И для этого не требуется делать 100500 запросов. Создатели сайтов ВУЗов - не дураки, тонна лишней инфы не нужна.
В этом проблема, что не всегда данные у ВУЗа качественные и полные. В одно время студенту нельзя было нормально посмотреть расписания препода. Только скачивать всё расписание и обрабатывать его.
Нет, это слишком нечасто для многих ВУЗов. Рад, если у вас всё за неделю публикуется, но это редкость.
Отсутствие возможности запросить последнее расписание вручную - это прям большая проблема в вашей идеи. Ваши контракты умеют в превентивное обновление?
Частоту всегда можно доработать. Остальная ответственность на конкретном бэке.
Не моя зона ответственности. И не ваша. И уж тем более не создателей интеграций.
Кстати, как это будете поддерживать, если аудитория стала занятой вот только что, а у вас обновление данных произойдёт спустя сутки? По клику преподавателя заново "скачивать интернет"?
А если не преподаватель нажмёт?..
Частоту обновления всегда можно настроить. То что это не ваша зона ответственности - понимаю, ваш выбор. Я просто говорю, что эта полезная фича, которую дёшево реализовать на бэке в примитивном варианте (анализ расписания по аудитории) и поддержать её отображение в приложении. Если конкретному бэку нужно что-то большее - он это реализует. Если бэк не хочет это реализовать - фича просто не будет доступна при выборе этого бэка.
А сможете разработать контракт, который покроет ВУЗы? Сможете интегрировать весь мир?
У меня не было наполеоновских планов по захвату мира) И контракт всегда можно дорабатывать, добавляя новые фичи и дорабатывать старые, чтобы покрыть как можно больше от потребностей ВУЗов.
Хотя бы с руководством сможете договориться, что логин/пароль от ЛК будет передаваться стороннему приложению?
Сейчас и так много приложений-поделок для ВУЗов работают по такому же принципу. Также логин и пароль нужно вводить в moodle. Не вижу в этом проблем.
> Не построили удобную систему заметок для себя
OneNote. В нём заведите одну страничку (не более) под дела, связанные с задачами по учёбе. Не благодарите.
А мне то зачем, я уже себе давно настроил obsidian с синхронизацией (а до этого Notion). Я просто говорю, что не все до этого доходят во время учёбы в ВУЗе. Знаю по себе из тех времён и своим одногруппникам. Фича заметок с привязкой к предмету просто позволяет не париться об этом многим людям. А те, кто уже настроил для себя другое приложение заметок - они просто могут не пользоваться. В этом и смысл.
И опять перегруженное приложение, которое всех бесит и всё делает неидеально.
Ну вот. Это больше ваше мнение. Мне не хватало в своё время чисто расписания без привязок и доп инфы.
Поэтому я и написал в конце комментария, что хорошо, что есть такие альтернативы, как ваше приложение для тех, кому остальное ничего не нужно.
Мне это неинтересно, спасибо за предложение.
Я вроде ничего и не предлагал)
Прошу прощения за сумбур, но по факту статья была прочитана плохо, либо в вашем идеальном мире таких проблем нет - объяснился за себя и за студентов, которым просто хочется рабочее, актуальное расписание, без лишнего гемора.
Ваша идея, как я считаю, очень не проработана - надеюсь, описал проблемы достаточно подробно.
Статью прочитал вполне нормальным темпом. Просто решил поделиться альтернативным путём, которым в своё время пошёл сам. И также почему выбрал такой путь с плюсами и минусами. В моей идее есть проблемы, как и у всех идей (и даже больше, чем вы описали) - об этом тоже вскользь упомянул в первом комментарии, что не смог всё это дожать полностью, так как под конец хотелось просто доделать хоть что-то для магистерской и выложить в гугл плей и немного отдохнуть от совмещения учёбы/работы.
Повторю ещё раз - я только за, если будут альтернативные приложения с разными подходами, так как каждый выберет по душе.
Не будет ли проблем с запуском синхронизации без захода в приложение? Ведь по сути пользователь не будет заходить в приложение месяцами, так как всё есть в локальном календаре и Android может начать ограничивать запуск синхронизации по идее.
Тоже в своё время пробовал сделать что-то подобное. На 2-3 курсе (2019-2021 годы) сперва для курсачей написал приложение для вуза (было суммарно до 10к загрузок до того, как гугл выпилил аккаунт кафедры, на котором было это приложение) Потом для диплома (2021-2022) писал приложение для всех ВУЗов под такие же лозунги (зачем создавать каждому под свой ВУЗ, когда можно пилить общее для всех ВУЗов) (по сути переписал с 0 на Compose с другой архитектурой свой курсач). Также для своего вуза поднимал бэк на Ktor (благо админы ВУЗа дали сервак для этого). Потом для магистерской (2023-2024) уже с меньшим энтузиазмом переписывал на KMP + CMP (Android + iOS + Web/js). (https://github.com/Edugma/app)
Сделал два отличающиеся от вашего приложения выбора:
Есть единый контракт с данными, не завязанными на конкретный ВУЗ. И для работы нужно поднять бэк, на нём выдавать данные в нужном формате и описать ручки бэка в определённом формате (пример https://github.com/mospolyhelper/Edugma/blob/main/contract.json).
Свои UI для расписания и сервисов ЛК вместо импорта в календарь.
По итогу скоуп задач оказался настолько огромным, а KMP + CMP сырым на тот момент (+ куча других проблем), что смог что-то нормальное доделать только к магистерской и выложить в гугл плей (на app store не хватило сил, хотя +-рабочее iOS приложение было готово к защите).
По выбору в сторону бэка относительно локального парсинга на устройстве: Плюсы:
Легче править ошибки в парсинге и обогащении данных, так как не нужно обновлять само приложение (были случаи, когда структуру json расписания резко меняли).
Данные намного чище и полнее. У групп, студентов, преподов, аудиторий в расписании есть описание (кафедра/направление). У преподов/студентов есть аватарки. Можно смотреть расписание по любой сущности, а не той, для которой есть расписание на сайте ВУЗа. Можно кликать по сущностям расписания, чтобы увидеть их расписание, так как все сущности между собой на бэке связываются. Без своего бэка слишком ограниченные данные и часть вещей вообще не сделать локально. А для другой части нужно выкачивать всё расписание ВУЗа несколько раз в день на каждом девайсе, что очень плохо для серверов ВУЗа.
Минусы:
Нужно найти, где хостить. На крайний случай можно просто держать всё расписание в гитхабе и обновлять его скриптом раз в день. Эффект будет тот же.
Нужно следить за сервером.
Нужно очень долго продумывать общий формат данных, который в будущем будет сложно поменять. Для расписания изучал форматы данных календарей Outlook, Google, чтобы придумать что-то общее. Для универсального формата RRULE пришлось переписывать либу парсинга на KMP и больше кейсов обрабатывать, чем для родного формата расписания ВУЗа.
По выбору своего UI вместо импорта в календари: В целом я не вижу проблемы иметь и свой UI, но и предоставлять синхронизацию с календарями на устройстве. Сам я вообще полноценно не пользовался календарём до 2024 года и эту фичу отложил в дальний ящик (так как за всё время её просило 1-2 человека).
Главный плюс своего UI - возможность отображать так, как будет удобнее для расписания занятий. Добавлять страницы с полной интерактивной информацией о расписании (Карта с аудиториями, когда они по всей Москве могут быть разбросаны. Другие группы, которые будут на этом занятии).
Быстрый просмотр расписания препода, группы, студента, аудитории просто по клику на них в информации о паре. На страничке для аудитории ещё можно график занятости и карту.
Можно добавить просмотр изменений в расписании (какие пары убраны, какие появились или изменились), просмотр свободных аудиторий (когда-то препод один предложил такую вещь сделать, так как была проблема с поиском такой аудитории).
Я намеренно не стал добавлять отображение расписания внутри приложения, чтобы студенты привыкали к календарю как инструменту
То есть не вижу смысла отказываться от собственного UI, разве только на первое время, если не хватает времени сделать его.
В личном кабинете функциональность зачастую ограничена семестровыми оценками
У нас был убогий лк, в который не хотелось заходить (но сейчас сделали новый силами студентов). Там кроме оценок, были заявки/справки (отправка и статусы), личные сообщения от преподов, поиск по преподам/студентам, и ещё какие-то сервисы, которые я уже не застал. Поэтому в целом имеет смысл доступ к сервисам лк через приложение с одинаково удобным интерфейсом для всех ВУЗов.
Отличаются ли заметки в приложении ВУЗа от заметок в любом другом приложении
Иногда удобно, чтобы заметки были прямо в расписании у конкретного занятия/предмета. Иначе они могут быть раскиданы по личке вк/тг и родному приложению с заметками без системы и будет наоборот тяжелее. Многие (да и я на тот момент) во время обучения в ВУЗе не построили удобную систему заметок для себя. Поэтому не вижу проблемы такой фичи. Кому она не нужна - просто не будут пользоваться.
Могут ли они повлиять на коварного преподавателя, занизив ему рейтинг в каком-то неофициальном приложении?
После появления Кампуса, нам препод на паре зачитывал негативные отзывы о себе) Фича полезна для того, чтобы понимать что за зверь будет у тебя в этом семестре. Хорошо бы ещё кроме отзывов туториалы делать, как его предмет проще сдать и какие причуды у него есть)
В целом хорошо, что появляются такие приложении. У студентов будет больше альтернатив из чего выбирать.
Статья топ. Появилось несколько вопросов по замерам: Как вы замеряли свою кастомную метрику Until Last Draw (адаптировали под macrobenchmark или вручную)? Какой перцентиль использован для сравнения метрик в статье?
Ещё есть опечатка (или пасхалка) с frameDurationCuMs
Заменяя случайные биты в 7 версии на время мы лишь приблизимся к производительности версии 6. Основная проблема - строковое представление в BASE16, что дольше делать, чем BASE32 + невозможность предгенерации префикса (или любой другой части) при запуске приложения
А нагенерить пул объектов, как уже предлагали выше - вполне хорошая идея, но нужно будет решить несколько корнер кейсов (многопоточка и если не успели заполнить пул, а требуются новые ID, чтобы не было деградаций)
По сути это такой же вариант, как и в статье по принципу (префикс (64 бита), сгенерированный один раз при запуске + счётчик (64 бита)). Только тут будет 128 бит рандомного префикса и 64 бита счётчика. Увеличение длины - это также дольше расчёт hashcode и больше памяти для хранения. Не уверен, насколько стоит так делать
где получение UUID существенно сказывается на производительности приложения и отражается на пользователе
Такого места нет. Это больше как один из этапов возможной оптимизации, который по отдельности вообще не будет заметен пользователю. Но несколько подобных этапов для слабый устройств вполне можно будет заметить.
В WB такого и вправду нету, так как использования UUID больше единичные (проверял по коду до выпуска статьи)
Насколько я вижу по структуре UUIDv7 и ULID похожи (временная метка (48 бит) + рандом (74 бита у UUIDv7 и 80 бит у ULID), поэтому отличий по времени в плане генерации объекта особо быть не должно.
Но у ULID строковой ID кодируется в BASE32, что ускоряет генерацию строкового ID, но всё равно придётся конвертировать все биты в строку (не получился предгенерировать один префикс при запуске).
Поэтому тут лучше взять UUIDv7 и нагенерировать пул значений, как предлагали выше. Или на крайний случай сохранять UUIDv7 в BASE32 формате.
Если человек поменял время в настройках, то временная метка тоже может поменяться. И есть очень маленький риск запустить приложение в один и тот же момент времени после смены времени в настройках. Для этого нужно случайное число, чтобы риск нивелировать до минимума.
Насчёт изменения счётчика внутри потока: вы предлагаете хранить счётчик в ThreadLocal, чтобы использовать обычный Long, а не AtomicLong?
Я не верю, что профилирование приложения показало что генерация UUID это узкое место
Профилирование этого и не показывало (обычно на экранах всегда есть проблемы похуже). Здесь больше про то, что в некоторых ситуациях (при разработке общих элементов) может оказаться, что особо оптимизировать нечего больше, но при этом в коде есть генерация UUID. Поэтому почему бы не рассмотреть, а нужен ли он в данном месте и можно ли его чем-то заменить, чтобы ускорить. И статья в этом плане просто эксперимент.
Бизнес требования будут меняться и раньше или позже (скорее раньше) вы со своего велосипеда упадете.
Так можно сказать и про автоинкрементальный ID в БД. И как показывает практика, от того, что в SQLite у нас автоинкрементальный ID (даже для элементов с бэка, у которых свой ID), из-за новых хотелок бизнеса не приходилось переделывать его на UUID. По аналогии почему тогда в похожих кейсах, где неудобно использовать автоинкремент из бд не использовать свою генерацию ID.
вы заменили стандартный инструмент, про достоинства и недостатки знают все, на какой-то свой велосипед
Есть такой фактор, но это не повод не пробовать сделать своё. В больших приложениях столько своих велосипедов из-за того, что стандартные решения часто не подходят или медленны в конкретных кейсах. И тем не менее нормально живут такие приложения. И тут уже нужно от конкретного случая смотреть, нужно ли в вашем коде такое или нет. Стандартных методов генерации ID (через бэк, автоинкремент в локальной бд или UUID.randomUUID()), вполне хватит в 95+% мест и тем более для средних приложений.
Метка времени запуска приложения может повториться на одном устройстве (с очень маленьким шансом). Поэтому было решено добавить случайное число. И так как префикс - Long, то просто решил до конца заполнить оставшиеся биты случайными числами.
Атомарный счётчик обычно медленнее, когда очень много потоков и большая конкурентность, что обычно не встретишь у мобилок. Поэтому атомарный счётчик вполне должен быть быстрее, чем мьютексы.
Если использовать номер потока, вместе с ним нужно получать временную метку каждый раз (а не только при запуске). Из-за этого нам придётся преобразовывать в строку больше значений, чем в случае, когда нам достаточно лишь время запуска и мы можем преобразовать в строку её одни раз при запуске.
mac адрес не добавляет уникальности, если ID будет использован только на данном устройстве (это требование было поставлено, как начальное условие для нового способа генерации ID).
Частота генерации может быть любая (от генерации множества ID на нескольких потоков в один момент времени до редкой генерации раз в секунду) + время может меняться на устройстве по другим причинам, поэтому только время и не подошло.
Просто счётчик не спасёт, так как при смерти процесса в Android всё исчезает и после перезапуска счётчик начнётся с нуля, при этом через механизм сохранения данных (либо onSaveInstanceState (и его альтернативы), либо другие локальные хранилища) могут быть сохранены эти ID и тогда они начнут конфликтовать с обнулённым счётчиком
В SQLite (так как рассматриваем именно мобилки) нету полноценной поддержки фичи SEQUENCE как в других БД. Только через автоинкремент поля ID. Если реализовывать через таблицу чисто для ID, то встаёт вопрос производительности, так как при чтении и записи в SQLite будет очень много действий (нужно тестировать)
Интересный подход, хотя тут и нужно решить много корнер кейсов с генерацией новых id в пул (запросили ID, сгенеренные закончились, новые не успели сгенериться), и очисткой пула, чтобы не держать лишние id. Также чтобы не было проблем с этими корнер кейсами в многопоточке. Ещё нужно тонко настроить пул, чтобы не был очень большим для памяти, при этом не очень маленьким, чтобы не было деградаций производительности при быстром израсходовании сгенеренных ID
Статья больше про применение этого метода на мобильных устройствах. Специально не затрагивал бэк, так как понимаю, что проблем будет куча и особо не пооптимизируешь тут. На мобилке в свою очередь прятать особо нечего, если ID не будет уходить на бэк. Поэтому тем уровнем безопасности UUID, который создавался для бэка, можно немного пренебречь в угоду производительности
Сразу скажу - я лишь поделился своим опытом и причиной выбора других решений без претензий к вашему подходу. И я только за, если будут альтернативные приложения с разными подходами, так как каждый выберет своё по душе.
Приложение делал в первую очередь для закрытия курсачей/диплома и для того, чтобы поиграться с архитектурой и технологиями. И в параллель этому чтобы сделать что-то полезное, а не для захвата всех ВУЗов)
Идея приложения - как идея moodle (система электронного образования, которую подключают себе вузы): предоставлять инструмент, которым могут воспользоваться. Android приложение moodle позволяет ввести url сайта, логин и пароль и не отвечает за контент каждого отдельного бэка. Оно просто даёт инструмент для её использования. Примерно с такой же идеей и решил делать приложение.
В целом ответы на вопросы ниже такие же, как и если бы эти вопросы были адресованы разрабам moodle.
Вполне в ВУЗах может найтись хотя бы 1 такой энтузиаст бeкэндер. С ВУЗом можно договориться, чтобы поднять бэк у него (да, не всегда пойдут на встречу, но мне вполне подняли, когда попросил через научрука). И этот проект можно оформить как курсовую/диплом (который ещё могут оценивать не так строго, так как работа на пользу ВУЗа).
Идея приложения, чтобы бэки сами отвечали за себя (как и у moodle)
Ничего, кроме хорошей темы для курсовой/диплома, фана и практики кодинга.
Будут проблемы у конкретной бэка. Последствия такие же, если кто-то напишет своё приложение для ВУЗа со своим бэком, хотя в гугл плее такие тоже есть и нормально работают. Также, если конкретный бэк для moodle сломается.
Никак. Люди просто не будут пользоваться этим бэком.
Обращаться к конкретному бэку, чтобы он чаще обновлял его.
С этой проблемой не встречался. Но опять же это на холдере бэка. Договориться с ВУЗом, возможно. Других вариантов в голову не приходит, так как не сталкивался с этим.
Частичная дока по контракту есть, но приложение в целом не очень доделано (описал это в первом комменте, что не осилил скоуп задачи и переделок, чтобы это пилить в параллель работы). Хотя планирую не делать ломающие изменения + добавить версионирование.
Тем что всё на бэке и для правки не нужно вносить изменение в приложение и всё сразу начнёт прилетать с бэка после фикса. Если делать локально, то нужно париться о каждом ВУЗе. И чем больше их - тем больше вероятность того, что нужно будет делать новый релиз. А это та ещё морока + время на ревью в разных сторах
Достукиваться и не планировал. В этом согласен - преимущество вашего подхода. Но сознательно выбирал именно подход moodle с его плюсами и минусами.
Тут пошла какая-то пассивная агрессия на нейтральный комментарий.
Мой ВУЗ предоставляет расписание только по группе. Для других сущностей расписание придётся через сложные способы вычислять. У некоторых ВУЗов могут быть данные ещё хуже. И чистота данных в плане того, что на бэке есть время скачивать кучу нужных данных у ВУЗа, обогащать и причёсывать данные. В случае локального парсинга - тут мы сильно ограничены, временем и нагрузкой на сервера ВУЗа (одно дело, когда один бэк выгружает кучу данных у ВУЗа, а другое дело, когда это будут делать тысячи студентов по несколько раз в день).
Когда у тебя в ВУЗе куча кафедр, становится полезно/интересно знать, с какой кафедры препод или с какой кафедры/направления группа, с которой у вас общее занятие.
Это просто ссылка на аватарку с лк ВУЗа. И для моего ВУЗа бэк запущен на сервере ВУЗа. Так что по сути всё хранится на серверах ВУЗа в любом из случаев)
В этом проблема, что не всегда данные у ВУЗа качественные и полные. В одно время студенту нельзя было нормально посмотреть расписания препода. Только скачивать всё расписание и обрабатывать его.
Частоту всегда можно доработать. Остальная ответственность на конкретном бэке.
Частоту обновления всегда можно настроить. То что это не ваша зона ответственности - понимаю, ваш выбор. Я просто говорю, что эта полезная фича, которую дёшево реализовать на бэке в примитивном варианте (анализ расписания по аудитории) и поддержать её отображение в приложении. Если конкретному бэку нужно что-то большее - он это реализует. Если бэк не хочет это реализовать - фича просто не будет доступна при выборе этого бэка.
У меня не было наполеоновских планов по захвату мира) И контракт всегда можно дорабатывать, добавляя новые фичи и дорабатывать старые, чтобы покрыть как можно больше от потребностей ВУЗов.
Сейчас и так много приложений-поделок для ВУЗов работают по такому же принципу. Также логин и пароль нужно вводить в moodle. Не вижу в этом проблем.
А мне то зачем, я уже себе давно настроил obsidian с синхронизацией (а до этого Notion). Я просто говорю, что не все до этого доходят во время учёбы в ВУЗе. Знаю по себе из тех времён и своим одногруппникам. Фича заметок с привязкой к предмету просто позволяет не париться об этом многим людям. А те, кто уже настроил для себя другое приложение заметок - они просто могут не пользоваться. В этом и смысл.
Ну вот. Это больше ваше мнение. Мне не хватало в своё время чисто расписания без привязок и доп инфы.
Поэтому я и написал в конце комментария, что хорошо, что есть такие альтернативы, как ваше приложение для тех, кому остальное ничего не нужно.
Я вроде ничего и не предлагал)
Статью прочитал вполне нормальным темпом. Просто решил поделиться альтернативным путём, которым в своё время пошёл сам. И также почему выбрал такой путь с плюсами и минусами. В моей идее есть проблемы, как и у всех идей (и даже больше, чем вы описали) - об этом тоже вскользь упомянул в первом комментарии, что не смог всё это дожать полностью, так как под конец хотелось просто доделать хоть что-то для магистерской и выложить в гугл плей и немного отдохнуть от совмещения учёбы/работы.
Повторю ещё раз - я только за, если будут альтернативные приложения с разными подходами, так как каждый выберет по душе.
Не будет ли проблем с запуском синхронизации без захода в приложение? Ведь по сути пользователь не будет заходить в приложение месяцами, так как всё есть в локальном календаре и Android может начать ограничивать запуск синхронизации по идее.
Тоже в своё время пробовал сделать что-то подобное.
На 2-3 курсе (2019-2021 годы) сперва для курсачей написал приложение для вуза (было суммарно до 10к загрузок до того, как гугл выпилил аккаунт кафедры, на котором было это приложение)
Потом для диплома (2021-2022) писал приложение для всех ВУЗов под такие же лозунги (зачем создавать каждому под свой ВУЗ, когда можно пилить общее для всех ВУЗов) (по сути переписал с 0 на Compose с другой архитектурой свой курсач). Также для своего вуза поднимал бэк на Ktor (благо админы ВУЗа дали сервак для этого).
Потом для магистерской (2023-2024) уже с меньшим энтузиазмом переписывал на KMP + CMP (Android + iOS + Web/js).
(https://github.com/Edugma/app)
Сделал два отличающиеся от вашего приложения выбора:
Есть единый контракт с данными, не завязанными на конкретный ВУЗ. И для работы нужно поднять бэк, на нём выдавать данные в нужном формате и описать ручки бэка в определённом формате (пример https://github.com/mospolyhelper/Edugma/blob/main/contract.json).
Свои UI для расписания и сервисов ЛК вместо импорта в календарь.
По итогу скоуп задач оказался настолько огромным, а KMP + CMP сырым на тот момент (+ куча других проблем), что смог что-то нормальное доделать только к магистерской и выложить в гугл плей (на app store не хватило сил, хотя +-рабочее iOS приложение было готово к защите).
По выбору в сторону бэка относительно локального парсинга на устройстве:
Плюсы:
Легче править ошибки в парсинге и обогащении данных, так как не нужно обновлять само приложение (были случаи, когда структуру json расписания резко меняли).
Данные намного чище и полнее. У групп, студентов, преподов, аудиторий в расписании есть описание (кафедра/направление). У преподов/студентов есть аватарки. Можно смотреть расписание по любой сущности, а не той, для которой есть расписание на сайте ВУЗа. Можно кликать по сущностям расписания, чтобы увидеть их расписание, так как все сущности между собой на бэке связываются. Без своего бэка слишком ограниченные данные и часть вещей вообще не сделать локально. А для другой части нужно выкачивать всё расписание ВУЗа несколько раз в день на каждом девайсе, что очень плохо для серверов ВУЗа.
Минусы:
Нужно найти, где хостить. На крайний случай можно просто держать всё расписание в гитхабе и обновлять его скриптом раз в день. Эффект будет тот же.
Нужно следить за сервером.
Нужно очень долго продумывать общий формат данных, который в будущем будет сложно поменять. Для расписания изучал форматы данных календарей Outlook, Google, чтобы придумать что-то общее. Для универсального формата RRULE пришлось переписывать либу парсинга на KMP и больше кейсов обрабатывать, чем для родного формата расписания ВУЗа.
По выбору своего UI вместо импорта в календари:
В целом я не вижу проблемы иметь и свой UI, но и предоставлять синхронизацию с календарями на устройстве. Сам я вообще полноценно не пользовался календарём до 2024 года и эту фичу отложил в дальний ящик (так как за всё время её просило 1-2 человека).
Главный плюс своего UI - возможность отображать так, как будет удобнее для расписания занятий.
Добавлять страницы с полной интерактивной информацией о расписании (Карта с аудиториями, когда они по всей Москве могут быть разбросаны. Другие группы, которые будут на этом занятии).
Быстрый просмотр расписания препода, группы, студента, аудитории просто по клику на них в информации о паре. На страничке для аудитории ещё можно график занятости и карту.
Можно добавить просмотр изменений в расписании (какие пары убраны, какие появились или изменились), просмотр свободных аудиторий (когда-то препод один предложил такую вещь сделать, так как была проблема с поиском такой аудитории).
То есть не вижу смысла отказываться от собственного UI, разве только на первое время, если не хватает времени сделать его.
У нас был убогий лк, в который не хотелось заходить (но сейчас сделали новый силами студентов). Там кроме оценок, были заявки/справки (отправка и статусы), личные сообщения от преподов, поиск по преподам/студентам, и ещё какие-то сервисы, которые я уже не застал. Поэтому в целом имеет смысл доступ к сервисам лк через приложение с одинаково удобным интерфейсом для всех ВУЗов.
Иногда удобно, чтобы заметки были прямо в расписании у конкретного занятия/предмета. Иначе они могут быть раскиданы по личке вк/тг и родному приложению с заметками без системы и будет наоборот тяжелее. Многие (да и я на тот момент) во время обучения в ВУЗе не построили удобную систему заметок для себя. Поэтому не вижу проблемы такой фичи. Кому она не нужна - просто не будут пользоваться.
После появления Кампуса, нам препод на паре зачитывал негативные отзывы о себе) Фича полезна для того, чтобы понимать что за зверь будет у тебя в этом семестре. Хорошо бы ещё кроме отзывов туториалы делать, как его предмет проще сдать и какие причуды у него есть)
В целом хорошо, что появляются такие приложении. У студентов будет больше альтернатив из чего выбирать.
Статья топ. Появилось несколько вопросов по замерам:
Как вы замеряли свою кастомную метрику Until Last Draw (адаптировали под macrobenchmark или вручную)?
Какой перцентиль использован для сравнения метрик в статье?
Ещё есть опечатка (или пасхалка) с frameDurationCuMs
Вы пишите со стороны бэкенда. Я больше смотрел в контексте генерации и хранении в мобильном приложении, в том же UI слое (нечастые кейсы, но бывают).
Про обсуждение Base32 - спасибо, посмотрю драфт.
Предгенерация префикса как один из способов оптимизации генерации. Но способ с предгенерацией пула UUID всё же кажется удачнее.
Заменяя случайные биты в 7 версии на время мы лишь приблизимся к производительности версии 6. Основная проблема - строковое представление в BASE16, что дольше делать, чем BASE32 + невозможность предгенерации префикса (или любой другой части) при запуске приложения
А нагенерить пул объектов, как уже предлагали выше - вполне хорошая идея, но нужно будет решить несколько корнер кейсов (многопоточка и если не успели заполнить пул, а требуются новые ID, чтобы не было деградаций)
По сути это такой же вариант, как и в статье по принципу (префикс (64 бита), сгенерированный один раз при запуске + счётчик (64 бита)). Только тут будет 128 бит рандомного префикса и 64 бита счётчика. Увеличение длины - это также дольше расчёт hashcode и больше памяти для хранения. Не уверен, насколько стоит так делать
Такого места нет. Это больше как один из этапов возможной оптимизации, который по отдельности вообще не будет заметен пользователю. Но несколько подобных этапов для слабый устройств вполне можно будет заметить.
В WB такого и вправду нету, так как использования UUID больше единичные (проверял по коду до выпуска статьи)
По поводу префикса - он и генерируется один раз при запуске. Цитата из статьи:
По поводу ThreadLocal + Long vs AtomicLong будет интересно сравнить, чтобы быстрее (при малой конкуренции потоков и при высокой)
Насколько я вижу по структуре UUIDv7 и ULID похожи (временная метка (48 бит) + рандом (74 бита у UUIDv7 и 80 бит у ULID), поэтому отличий по времени в плане генерации объекта особо быть не должно.
Но у ULID строковой ID кодируется в BASE32, что ускоряет генерацию строкового ID, но всё равно придётся конвертировать все биты в строку (не получился предгенерировать один префикс при запуске).
Поэтому тут лучше взять UUIDv7 и нагенерировать пул значений, как предлагали выше. Или на крайний случай сохранять UUIDv7 в BASE32 формате.
Если человек поменял время в настройках, то временная метка тоже может поменяться. И есть очень маленький риск запустить приложение в один и тот же момент времени после смены времени в настройках. Для этого нужно случайное число, чтобы риск нивелировать до минимума.
Насчёт изменения счётчика внутри потока: вы предлагаете хранить счётчик в ThreadLocal, чтобы использовать обычный Long, а не AtomicLong?
Код с UUID, который побудил изучить эту тему был реальный (на одном из прошлых проектов). Но реализация собственного ID в реальном коде не применялась
Профилирование этого и не показывало (обычно на экранах всегда есть проблемы похуже). Здесь больше про то, что в некоторых ситуациях (при разработке общих элементов) может оказаться, что особо оптимизировать нечего больше, но при этом в коде есть генерация UUID. Поэтому почему бы не рассмотреть, а нужен ли он в данном месте и можно ли его чем-то заменить, чтобы ускорить. И статья в этом плане просто эксперимент.
Так можно сказать и про автоинкрементальный ID в БД. И как показывает практика, от того, что в SQLite у нас автоинкрементальный ID (даже для элементов с бэка, у которых свой ID), из-за новых хотелок бизнеса не приходилось переделывать его на UUID. По аналогии почему тогда в похожих кейсах, где неудобно использовать автоинкремент из бд не использовать свою генерацию ID.
Есть такой фактор, но это не повод не пробовать сделать своё. В больших приложениях столько своих велосипедов из-за того, что стандартные решения часто не подходят или медленны в конкретных кейсах. И тем не менее нормально живут такие приложения. И тут уже нужно от конкретного случая смотреть, нужно ли в вашем коде такое или нет. Стандартных методов генерации ID (через бэк, автоинкремент в локальной бд или UUID.randomUUID()), вполне хватит в 95+% мест и тем более для средних приложений.
Метка времени запуска приложения может повториться на одном устройстве (с очень маленьким шансом). Поэтому было решено добавить случайное число. И так как префикс - Long, то просто решил до конца заполнить оставшиеся биты случайными числами.
Атомарный счётчик обычно медленнее, когда очень много потоков и большая конкурентность, что обычно не встретишь у мобилок. Поэтому атомарный счётчик вполне должен быть быстрее, чем мьютексы.
Если использовать номер потока, вместе с ним нужно получать временную метку каждый раз (а не только при запуске). Из-за этого нам придётся преобразовывать в строку больше значений, чем в случае, когда нам достаточно лишь время запуска и мы можем преобразовать в строку её одни раз при запуске.
(не туда ответил)
(не туда ответил)
mac адрес не добавляет уникальности, если ID будет использован только на данном устройстве (это требование было поставлено, как начальное условие для нового способа генерации ID).
Частота генерации может быть любая (от генерации множества ID на нескольких потоков в один момент времени до редкой генерации раз в секунду) + время может меняться на устройстве по другим причинам, поэтому только время и не подошло.
Просто счётчик не спасёт, так как при смерти процесса в Android всё исчезает и после перезапуска счётчик начнётся с нуля, при этом через механизм сохранения данных (либо onSaveInstanceState (и его альтернативы), либо другие локальные хранилища) могут быть сохранены эти ID и тогда они начнут конфликтовать с обнулённым счётчиком
В SQLite (так как рассматриваем именно мобилки) нету полноценной поддержки фичи SEQUENCE как в других БД. Только через автоинкремент поля ID. Если реализовывать через таблицу чисто для ID, то встаёт вопрос производительности, так как при чтении и записи в SQLite будет очень много действий (нужно тестировать)
Интересный подход, хотя тут и нужно решить много корнер кейсов с генерацией новых id в пул (запросили ID, сгенеренные закончились, новые не успели сгенериться), и очисткой пула, чтобы не держать лишние id. Также чтобы не было проблем с этими корнер кейсами в многопоточке. Ещё нужно тонко настроить пул, чтобы не был очень большим для памяти, при этом не очень маленьким, чтобы не было деградаций производительности при быстром израсходовании сгенеренных ID
Статья больше про применение этого метода на мобильных устройствах. Специально не затрагивал бэк, так как понимаю, что проблем будет куча и особо не пооптимизируешь тут. На мобилке в свою очередь прятать особо нечего, если ID не будет уходить на бэк. Поэтому тем уровнем безопасности UUID, который создавался для бэка, можно немного пренебречь в угоду производительности