Больше почитать можно в каналах других участников нашей команды:
- 99developers — канал Саши Андронова, нашего CTO. Сейчас пишет про стартап
- Рубанов про мобилу — канал Миши Рубанова. Много про iOS разработку и мобильную разработку вообще
- 99developers — канал Саши Андронова, нашего CTO. Сейчас пишет про стартап
- Рубанов про мобилу — канал Миши Рубанова. Много про iOS разработку и мобильную разработку вообще
Telegram
99developers
Делаю банк для мигрантов.
Построил IT в Додо.
DM: @alexandronov
Построил IT в Додо.
DM: @alexandronov
❤1
Kotlin Guard Conditions
В Kotlin 2.1.0 появилась экспериментальная фича, которая по умолчанию выключена — guard conditions в
Теперь можно писать дополнительные условия прямо в ветках when, не теряя преимущества exhaustiveness. Пример можно увидеть на скриншоте.
Раньше приходилось:
— либо писать вложенные if'ы внутри ветки
— либо использовать when без аргумента (и терять исчерпывающую проверку)
Теперь можно писать короче, чище и при этом получать ошибки компиляции, если забыли обработать кейс.
Важно помнить, что, как у любой конструкции языка, у guard condition есть своя область применения. Иногда лучше написать вложенный if (например, для читаемости или для выполнения рефакторинга). Нужно смотреть по ситуации.
❗️ Фича экспериментальная. Сейчас чтобы включить фичу нужно прописать специальный флаг для компилятора:
💭 А вы уже включили guard condition?
В Kotlin 2.1.0 появилась экспериментальная фича, которая по умолчанию выключена — guard conditions в
when.Теперь можно писать дополнительные условия прямо в ветках when, не теряя преимущества exhaustiveness. Пример можно увидеть на скриншоте.
Раньше приходилось:
— либо писать вложенные if'ы внутри ветки
— либо использовать when без аргумента (и терять исчерпывающую проверку)
Теперь можно писать короче, чище и при этом получать ошибки компиляции, если забыли обработать кейс.
Важно помнить, что, как у любой конструкции языка, у guard condition есть своя область применения. Иногда лучше написать вложенный if (например, для читаемости или для выполнения рефакторинга). Нужно смотреть по ситуации.
❗️ Фича экспериментальная. Сейчас чтобы включить фичу нужно прописать специальный флаг для компилятора:
android {
...
kotlinOptions {
freeCompilerArgs = listOf("-XXLanguage:+WhenGuards")
}
}💭 А вы уже включили guard condition?
🔥4
⏰ Instant и Clock — deprecated
Если вы обновите
Исчезают kotlinx.datetime.Instant и kotlinx.datetime.Clock.
😱 WUUUT?
Разработчики сжалились и выпустили
Что происходит?
Начиная с Kotlin 2.1 типы Instant и Clock официально переезжают в стандартную библиотеку — в пакет
Вот ссылки на новые версии:
🔗 Instant
🔗 Clock
Если вы обновите
kotlinx-datetime до версии 0.7.0, проект, скорее всего, перестанет собираться. Исчезают kotlinx.datetime.Instant и kotlinx.datetime.Clock.
😱 WUUUT?
Разработчики сжалились и выпустили
0.7.1, где временно добавили typealias'ы для обратной совместимости.Что происходит?
Начиная с Kotlin 2.1 типы Instant и Clock официально переезжают в стандартную библиотеку — в пакет
kotlin.time.Вот ссылки на новые версии:
🔗 Instant
🔗 Clock
📦 Миграция на kotlinx-datetime 0.7.1 — что нужно знать
Если используете kotlinx-datetime, просто обновитесь до
— у вас нет зависимостей от библиотек, которые требуют старую версию kotlinx-datetime
— вы не сериализуете Instant через kotlinx-serialization (если да — обновитесь до 1.9.0+)
Если после обновления ловите ClassNotFoundException на Instant или Clock, значит какая-то библиотека ещё не обновилась.
🔧 В этом случае можно временно использовать совместимую версию:
0.7.1-0.6.x-compat — она содержит старые классы для обратной совместимости.
Но лучше использовать только в крайнем случае.
Более подробно о миграции можно прочитать в репозитории: https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#deprecation-of-instant
Если используете kotlinx-datetime, просто обновитесь до
0.7.1. Всё должно работать, если:— у вас нет зависимостей от библиотек, которые требуют старую версию kotlinx-datetime
— вы не сериализуете Instant через kotlinx-serialization (если да — обновитесь до 1.9.0+)
Если после обновления ловите ClassNotFoundException на Instant или Clock, значит какая-то библиотека ещё не обновилась.
🔧 В этом случае можно временно использовать совместимую версию:
0.7.1-0.6.x-compat — она содержит старые классы для обратной совместимости.
Но лучше использовать только в крайнем случае.
Более подробно о миграции можно прочитать в репозитории: https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#deprecation-of-instant
GitHub
GitHub - Kotlin/kotlinx-datetime: KotlinX multiplatform date/time library
KotlinX multiplatform date/time library. Contribute to Kotlin/kotlinx-datetime development by creating an account on GitHub.
Говоря о технологических крысах... я только что попробовал новый фреймворк 😅
🎛 Flocon — инструмент, о котором недавно писал Кирилл Розов у себя в канале. Хочу поделиться впечатлениями — кажется, штука действительно заслуживает внимания.
Я вообще люблю всякие утилиты, которые упрощают разработку. В частности, мне всегда нравился Flipper от Facebook. Судя по всему, я не один такой — вот буквально только что Максим Качинкин писал об этом же у себя (кстати, если ещё не подписаны — советую: https://t.me/mobilefiction).
Поэтому я не мог обойти стороной инструмент, который:
- внешне очень похож на Flipper
- сам автор пишет, что он inspired by Flipper
- написан на Kotlin Multiplatform + Compose Multiplatform
💥 Решил сразу с ноги интегрировать Flocon в Jazari.
Что пошло так, а что не очень — расскажу в следующем посте 👀
🎛 Flocon — инструмент, о котором недавно писал Кирилл Розов у себя в канале. Хочу поделиться впечатлениями — кажется, штука действительно заслуживает внимания.
Я вообще люблю всякие утилиты, которые упрощают разработку. В частности, мне всегда нравился Flipper от Facebook. Судя по всему, я не один такой — вот буквально только что Максим Качинкин писал об этом же у себя (кстати, если ещё не подписаны — советую: https://t.me/mobilefiction).
Поэтому я не мог обойти стороной инструмент, который:
- внешне очень похож на Flipper
- сам автор пишет, что он inspired by Flipper
- написан на Kotlin Multiplatform + Compose Multiplatform
💥 Решил сразу с ноги интегрировать Flocon в Jazari.
Что пошло так, а что не очень — расскажу в следующем посте 👀
Telegram
Android Broadcast
🐱 Flocon - open source инструмент для отладки и инспекции Android приложений
Что умеет инструмент:
👉 Отслеживание сетевых запросов
👉 Просмотр файлов, баз данных и shared pref
👉 Дебаг меню с десктопа
👉 Работа c deeplink
Для работы необходимо подключение…
Что умеет инструмент:
👉 Отслеживание сетевых запросов
👉 Просмотр файлов, баз данных и shared pref
👉 Дебаг меню с десктопа
👉 Работа c deeplink
Для работы необходимо подключение…
👍5
🚀 Flocon — первый взгляд
Итак, попробовал новый инструмент Flocon — аналог Flipper, но на KMP + Compose Multiplatform. Делюсь первыми впечатлениями:
✅ Плюсы:
— Гибкость — реально гибче, чем Flipper
— Я пока не видел нативного кода. Если его правда нет, то поддержка 16KB страниц памяти не будет требоваться, как было с Flipper
— Популярность — проекту неделя, а уже куча звёзд. Люди пробуют и им заходит
— Скорость — десктопная версия на KMP работает намного быстрее, чем Flipper
— Дашборды — пушка 💥
— Активное развитие — автор активно ревьюит PR’ы, отвечает, обсуждает идеи
⚠️ Нюансы:
— Проекту неделя — решайте сами, плюс это или минус 🙂 📅
— Проблемы с изображениями — сначала показывались чёрные квадраты. Заработало после запуска dev-версии из IDE 🖼
— UI десктопного клиента сыроват — не хватает базовых удобств: сортировки, закреплений, базовой навигации 🧱
— Нет no-op реализации — issue есть, но автор пока не горит её делать. Чтобы не пропустить в прод лишний код, нужна хорошая модуляризация. В некоторых случаях может потребоваться переработка архитектуры — может не подойти некоторым проектам 🚫
— minSdk 24 — кому-то может быть критично 📱
— iOS не поддерживается и я пока не видел планов (Flipper умеет работать с iOS) 🍏
Итак, попробовал новый инструмент Flocon — аналог Flipper, но на KMP + Compose Multiplatform. Делюсь первыми впечатлениями:
✅ Плюсы:
— Гибкость — реально гибче, чем Flipper
— Я пока не видел нативного кода. Если его правда нет, то поддержка 16KB страниц памяти не будет требоваться, как было с Flipper
— Популярность — проекту неделя, а уже куча звёзд. Люди пробуют и им заходит
— Скорость — десктопная версия на KMP работает намного быстрее, чем Flipper
— Дашборды — пушка 💥
— Активное развитие — автор активно ревьюит PR’ы, отвечает, обсуждает идеи
⚠️ Нюансы:
— Проекту неделя — решайте сами, плюс это или минус 🙂 📅
— Проблемы с изображениями — сначала показывались чёрные квадраты. Заработало после запуска dev-версии из IDE 🖼
— UI десктопного клиента сыроват — не хватает базовых удобств: сортировки, закреплений, базовой навигации 🧱
— Нет no-op реализации — issue есть, но автор пока не горит её делать. Чтобы не пропустить в прод лишний код, нужна хорошая модуляризация. В некоторых случаях может потребоваться переработка архитектуры — может не подойти некоторым проектам 🚫
— minSdk 24 — кому-то может быть критично 📱
— iOS не поддерживается и я пока не видел планов (Flipper умеет работать с iOS) 🍏
👍2
🚀 Что сделали в Jazari за последние 2 месяца
Мы наконец-то запустились.
Полноценный банковский сервис. С нуля.
До сих пор звучит как безумие 😅
По продукту:
— в июле пошли в прод. После тестовых открытий аккаунтов и переводов денег начали регистрировать реальных пользователей
— активность выше, чем ожидали: заказывают карты, делают покупки, переводят деньги, берут кредиты
— пускаем по очереди, сейчас >2000 человек. Цель на август — 5000+. Часть проверки автоматизирована, но без ручной работы пока никак, поэтому 2000 — хороший результат
✅ Запуск прошел довольно удачно. По приложениям и апи был минимум нареканий, в основном не учли редкие кейсы.
❗️На запуске оказалось, что мы плохо обучаем пользователя на входе, из-за чего в саппорт прилетает много однотипных вопросов
Мы наконец-то запустились.
Полноценный банковский сервис. С нуля.
До сих пор звучит как безумие 😅
По продукту:
— в июле пошли в прод. После тестовых открытий аккаунтов и переводов денег начали регистрировать реальных пользователей
— активность выше, чем ожидали: заказывают карты, делают покупки, переводят деньги, берут кредиты
— пускаем по очереди, сейчас >2000 человек. Цель на август — 5000+. Часть проверки автоматизирована, но без ручной работы пока никак, поэтому 2000 — хороший результат
✅ Запуск прошел довольно удачно. По приложениям и апи был минимум нареканий, в основном не учли редкие кейсы.
❗️На запуске оказалось, что мы плохо обучаем пользователя на входе, из-за чего в саппорт прилетает много однотипных вопросов
🔥4
🐛 Самое серьёзное, что прилетело — на ошибки загрузки данных мы показывали Ooops экран. Он попадался часто и создавал ощущение, что с приложением всё очень и очень плохо. Дошло до того, что CTO ввёл мораторий на Ooops экран 😁
Экран пока не убрали, но стали показывать реже, добавили ретраи, стабилизировали поведение. Пользовательский опыт стал значимо лучше.
Экран пока не убрали, но стали показывать реже, добавили ретраи, стабилизировали поведение. Пользовательский опыт стал значимо лучше.
👍3😁1
📱 Что нового в Jazari
— При регистрации выяснилось: у многих нет паспорта под рукой, зато есть права. Теперь принимаем водительское удостоверение 🚗
— Запустили предзаказ лимитированной карты (на скрине). Пока без рекламы. Видео и анимация — покажу отдельно ✨
— Ввели кэшбэк с ревордами с Waitlist. Для многих это главный мотиватор зарегистрироваться. До этого часть людей закрывала аккаунты из-за отсутствия бонуса 💰
— Главный экран — переделали уже дважды 🤔
— Экран перевода денег — трижды 🤯
— С кредитами: хотят многие, но разрешено меньше, чем планировали. Тем, кому нельзя, пробуем аккуратно объяснять причину — уже 3 варианта UX, и продолжаем улучшать 💸
— Новая кредитная программа — можно брать кредит даже без своих денег на счету. Пользуются активно 💸
— Много потенциальных фродеров — часть аккаунтов закрыли 🕵️♀️
— Некоторые сами закрывают аккаунты. Теперь собираем причины и рассказываем о будущих улучшениях. Иногда помогает оставить пользователя. 🛑
— При регистрации выяснилось: у многих нет паспорта под рукой, зато есть права. Теперь принимаем водительское удостоверение 🚗
— Запустили предзаказ лимитированной карты (на скрине). Пока без рекламы. Видео и анимация — покажу отдельно ✨
— Ввели кэшбэк с ревордами с Waitlist. Для многих это главный мотиватор зарегистрироваться. До этого часть людей закрывала аккаунты из-за отсутствия бонуса 💰
— Главный экран — переделали уже дважды 🤔
— Экран перевода денег — трижды 🤯
— С кредитами: хотят многие, но разрешено меньше, чем планировали. Тем, кому нельзя, пробуем аккуратно объяснять причину — уже 3 варианта UX, и продолжаем улучшать 💸
— Новая кредитная программа — можно брать кредит даже без своих денег на счету. Пользуются активно 💸
— Много потенциальных фродеров — часть аккаунтов закрыли 🕵️♀️
— Некоторые сами закрывают аккаунты. Теперь собираем причины и рассказываем о будущих улучшениях. Иногда помогает оставить пользователя. 🛑
👍1
🛠 Технические обновления
— Полностью переделали систему аналитики: добавлять события теперь супер просто, вся документация в одном месте, Android и iOS синхронизированы 📊
— Для отладки (только дев-версии) добавили:
• Chucker
• Flocon
• Шеринг логов устройства прямо из приложения
• для Flocon понадобилась модуляризация. Очень хотел это отложить, но не вышло. Сделал по аналогии с Now In Android — крупные утилитарные модули, крупные модули фич (пока без деления на апи/реализацию, но скоро тоже придётся делать) и app-модули
— Ещё раз прикрутили libphonenumber — расскажу отдельно ☎️
— Часть логики билда вынесли в Convention Plugins — стало проще поддерживать
— В приложении много Bottom Sheet, поэтому сделали своё API поверх Material — получилось удобно, думаю рассказать 📱
— Полностью переделали систему аналитики: добавлять события теперь супер просто, вся документация в одном месте, Android и iOS синхронизированы 📊
— Для отладки (только дев-версии) добавили:
• Chucker
• Flocon
• Шеринг логов устройства прямо из приложения
• для Flocon понадобилась модуляризация. Очень хотел это отложить, но не вышло. Сделал по аналогии с Now In Android — крупные утилитарные модули, крупные модули фич (пока без деления на апи/реализацию, но скоро тоже придётся делать) и app-модули
— Ещё раз прикрутили libphonenumber — расскажу отдельно ☎️
— Часть логики билда вынесли в Convention Plugins — стало проще поддерживать
build.gradle и добавлять модули ⚙️— В приложении много Bottom Sheet, поэтому сделали своё API поверх Material — получилось удобно, думаю рассказать 📱
👍5
Forwarded from 99developers (Alex Andronov)
С апдейтами для вас.
- включили международные переводы. С такими рейтами что хрен с нами кто поконкурирует. Пока не промоутим.
- запустили 1% кэшбека всем кто рефералил в вейтлисте. Им оставим все это на постоянке.
- 2,500 транзактящих пользователей. Конверсия от активного аккаунта в транзактящего пользователя больше 65%, неплохо.
- отладили ревью и комплаенс.
- кредиты растут так что к четвергу мы обычно перекрываем результат прошлой недели. Выплаты пока в норме, просрочки есть, но их оч мало.
- выключил вейтлист, получил леща от Миши, включил вейтлист обратно.
- встроили AI агента в чат в админке.
- начали делать SMM AI агента. Идея чтобы было дофига AI сотрудников живет и развивается.
- включили международные переводы. С такими рейтами что хрен с нами кто поконкурирует. Пока не промоутим.
- запустили 1% кэшбека всем кто рефералил в вейтлисте. Им оставим все это на постоянке.
- 2,500 транзактящих пользователей. Конверсия от активного аккаунта в транзактящего пользователя больше 65%, неплохо.
- отладили ревью и комплаенс.
- кредиты растут так что к четвергу мы обычно перекрываем результат прошлой недели. Выплаты пока в норме, просрочки есть, но их оч мало.
- выключил вейтлист, получил леща от Миши, включил вейтлист обратно.
- встроили AI агента в чат в админке.
- начали делать SMM AI агента. Идея чтобы было дофига AI сотрудников живет и развивается.
🔥2
🚀 Firebase Real-Time Remote Config
С Firebase можно получать оповещения об изменении Remote Config.
Без real-time оставалось два варианта:
— ждать N часов для обновления ⏳
— дёргать fetch слишком часто и упираться в квоту 😵💫
Real-Time Remote Config позволяет запрашивать конфиг ровно тогда, когда он реально поменялся.
Как это устроено:
— клиент держит соединение с сервером Real-time Remote Config
— сервер шлёт сигнал об инвалидации
— клиент сам вызывает fetch (но не activate — важно)
Дальше решаете сами: применять сразу, вызвав activate, или, например, только при следующем старте.
⚙️ Чтобы включить real-time, нужно:
— в GCP включить Firebase Remote Config Realtime API (иначе listener молчит)
— добавить
Выглядит магически: меняешь флаг в консоли → приложение само узнаёт и реагирует.
С Firebase можно получать оповещения об изменении Remote Config.
Без real-time оставалось два варианта:
— ждать N часов для обновления ⏳
— дёргать fetch слишком часто и упираться в квоту 😵💫
Real-Time Remote Config позволяет запрашивать конфиг ровно тогда, когда он реально поменялся.
Как это устроено:
— клиент держит соединение с сервером Real-time Remote Config
— сервер шлёт сигнал об инвалидации
— клиент сам вызывает fetch (но не activate — важно)
Дальше решаете сами: применять сразу, вызвав activate, или, например, только при следующем старте.
⚙️ Чтобы включить real-time, нужно:
— в GCP включить Firebase Remote Config Realtime API (иначе listener молчит)
— добавить
addOnConfigUpdateListenerВыглядит магически: меняешь флаг в консоли → приложение само узнаёт и реагирует.
👍1😢1
❓ Подводные камни Firebase Real-Time Remote Config
Вот детали, о которых нужно помнить:
1️⃣ Нет гарантии доставки. Соединение с сервером может не установиться или разорваться. Вроде SDK обрабатывает это, но на практике обновления иногда «теряются»
2️⃣ Долгоживущее HTTP-соединение → дополнительный расход батареи и ресурсы
3️⃣ Нужно продумать активацию. Иначе рискуете: приложение стартовало в одном состоянии, а внезапно переключилось в другое
4️⃣ Конфиг может обновиться, пока приложение закрыто. Тогда апдейт дойдёт только через несколько секунд после старта. Если не вызвать
Вот детали, о которых нужно помнить:
1️⃣ Нет гарантии доставки. Соединение с сервером может не установиться или разорваться. Вроде SDK обрабатывает это, но на практике обновления иногда «теряются»
2️⃣ Долгоживущее HTTP-соединение → дополнительный расход батареи и ресурсы
3️⃣ Нужно продумать активацию. Иначе рискуете: приложение стартовало в одном состоянии, а внезапно переключилось в другое
4️⃣ Конфиг может обновиться, пока приложение закрыто. Тогда апдейт дойдёт только через несколько секунд после старта. Если не вызвать
activate сразу — изменения попадут лишь на следующем запуске. Иногда это ок, иногда критично👍1
💁♂️ На техдолг можно забить
.
.
.
если любите запах горящего прода по утрам
Одно утро началось с "у нас жопка с Intercom" от CTO. Пользователи в поддержке видят чужие сообщения.
Нашли статью, собрались консилиумом. Я читаю — и понимаю: накосячил я.
Хронология фиаско:
— очень давно завёл Account с id "на будущее", оставил TODO (на скрине). Тогда бэк еще не присылал id, поэтому оставил так;
— позже добавил чтение id из JWT, но не для Account;
— когда понадобилось использовать id, в одном месте взял его из JWT, а в другом — из Account.
Бомба взорвалась, когда пользователи с одинаковым именем пришли в саппорт.
Хотфикснули, почистили пользователей.
Вывод: техдолг обычно не взрывается сразу. Он копится и стреляет в самый неожиданный момент. Не копите техдолг.
.
.
.
если любите запах горящего прода по утрам
Одно утро началось с "у нас жопка с Intercom" от CTO. Пользователи в поддержке видят чужие сообщения.
Нашли статью, собрались консилиумом. Я читаю — и понимаю: накосячил я.
Хронология фиаско:
— очень давно завёл Account с id "на будущее", оставил TODO (на скрине). Тогда бэк еще не присылал id, поэтому оставил так;
— позже добавил чтение id из JWT, но не для Account;
— когда понадобилось использовать id, в одном месте взял его из JWT, а в другом — из Account.
Бомба взорвалась, когда пользователи с одинаковым именем пришли в саппорт.
Хотфикснули, почистили пользователей.
Вывод: техдолг обычно не взрывается сразу. Он копится и стреляет в самый неожиданный момент. Не копите техдолг.
👍6😱1
🪛 Архитектура Android-приложений
На Хабре и в других блогах регулярно выходят статьи про архитектуру Android приложений. Особенно часто — про устройство presentation слоя: вью, вью модель, немного затрагивают домен, почти никогда внешние зависимости.
Это любопытно: несмотря на официальные рекомендации Google, сообщество продолжает искать свои решения.
Почему?
Гайдлайны от Google (как и любые другие) дают каркас, но в реальных проектах остаётся много открытых вопросов. Их сложно закрыть одним рецептом: разные ожидания от продукта, окружение, требования по безопасности и UX часто конфликтуют — отсюда новые компромиссные подходы.
Если сказать кратко, любое «плохое» решение в проекте можно оправдать его эволюцией 😆
Пара интересных статей последних месяцев:
• Compose + Koin + Jetpack Navigation: что мы поняли за 2 года
• Демоприложения: как жить, когда у вас 90+ application-модулей
• Разбираем чистую архитектуру в Android: от а до я
• Функциональное программирование в Android. Побочные эффекты и ELM-архитектура
• Архитектура Android. Понятно и подробно
На Хабре и в других блогах регулярно выходят статьи про архитектуру Android приложений. Особенно часто — про устройство presentation слоя: вью, вью модель, немного затрагивают домен, почти никогда внешние зависимости.
Это любопытно: несмотря на официальные рекомендации Google, сообщество продолжает искать свои решения.
Почему?
Гайдлайны от Google (как и любые другие) дают каркас, но в реальных проектах остаётся много открытых вопросов. Их сложно закрыть одним рецептом: разные ожидания от продукта, окружение, требования по безопасности и UX часто конфликтуют — отсюда новые компромиссные подходы.
Если сказать кратко, любое «плохое» решение в проекте можно оправдать его эволюцией 😆
Пара интересных статей последних месяцев:
• Compose + Koin + Jetpack Navigation: что мы поняли за 2 года
• Демоприложения: как жить, когда у вас 90+ application-модулей
• Разбираем чистую архитектуру в Android: от а до я
• Функциональное программирование в Android. Побочные эффекты и ELM-архитектура
• Архитектура Android. Понятно и подробно
👍4
Какую версию студии используете?
Anonymous Poll
86%
Только стабильная версия
3%
Только Canary
11%
Установлено обе версии