Pavel Korolev


Channel's geo and language: World, Russian
Category: Technologies


12 лет как Android разработчик. Технологии, музыка, рефлексия и случайные мысли.
https://pavelkorolev.xyz - @pavelkorolevxyz

Related channels

Channel's geo and language
World, Russian
Statistics
Posts filter


Вчера провели свой первый андроид митап. Мне понравилось.

В первый раз прошёл с обратной стороны вот этих всех мероприятий. За все организационные моменты спасибо нашему деврелу Антону и всем ему помогающим, за это голова вообще не болела.

Но всё равно поболела о другом, последние дни были довольно напряжные. Почти в одном лице побыл программным комитетом, благо все спикеры (Илья, Чингис, Лёша) молодцы и был во всех уверен. Чуть чуть помог с подготовкой и вообще накидыванием идей. А в итоге ещё и ведущим поработал. Это всё новый опыт для меня. В какой-то степени спикером даже быть попроще, потому что ты сконцентрирован на своей теме и тебя не сильно волнует всё мероприятие в целом.

Забавный момент, если ты участвуешь в подготовке доклада, то он неминуемо подстраивается под твои интересы и вкусы, поэтому мне лично было интересно их все послушать в финальном варианте. Разница с прогонами огромная, конечно.

Остался интересный инсайт, что у нас оказывается какой-то недооценённый ресурс есть и мы можем регистрацию на несколько десятков человек забить буквально за сутки перепостив анонс по своим каналам и чатам. Понятно, что для нас это какое-то новое начинание и многие пришли хотя бы просто поддержать, но это явно можно использовать. Интерес в местном комьюнити есть, если есть какая-то классная андроид-повестка.

Вроде получилось прям неплохо, и доклады в итоге ребята рассказали хорошо, темы получились не самые банальные. И пообщались классно, сам унёс к себе несколько мыслей на подумать. Хотелось бы только, чтобы в будущем запись была, но будем считать вчерашний митап удачной проверкой гипотезы. Всем ещё раз спасибо кто пришёл, всем спасибо за обратную связь. 🙂

Фоточка за авторством наших коллег с последнего ряда.


Опять про DI. Koin

По всем каналам в последние дни пролетели перепосты роадмапа Koin. Я его зачем-то почитал и задумался дольше, чем должен был.

Чисто как разраб разраба я понимаю автора. Делает какие-то прикольные штуки, KMP там, какие-то оптимизации, компиляторные плагины пишет, аннотации обрабатывает, с композом интегрирует. Работа мечты практически. Но как пользователь я и коин вообще на разных полюсах как будто. Потому что на кой фиг мне это всё вообще в библиотеке для DI? Ты сам придумал проблемы и сам их теперь героически решаешь.

Начиналось всё с того, что это была чуть более умная мапа классов к их экземплярам. Решала проблему сложности популярных на тот момент даггеров с одной стороны и невозможность вызова конструкторов у системных классов напрямую с другой стороны. Своих нюансов добавляла, типа того, что на всех собесах стали душнить вопросами про сервис-локаторы, но брала своей "простотой". С тех пор много воды утекло, появились всякие хилты, которые благодаря маркетинговой машине гугла и решению первой из проблем стали де факто стандартом для новичков. И я в сравнении с коином это даже одобряю, хоть они оба мне и не нравятся.

Если не касаться каких-то фундаментальных вопросов, то просто кажется, что коин со временем превратился в какой-то волшебный космолёт со своим языком, разными вариантами сделать одно и то же, и всё так же без гарантий, что он не развалится в полёте.

И нужен он всё также исключительно для того, чтобы достать зависимость "откуда-то", вообще не думая откуда. То есть для заметания под ковёр комплексности нашего графа зависимостей. Типа чтобы вот эти тупые разрабы (включая тебя) вообще голову не включали насколько всрато этот граф реализован. И это ещё и ценой рантайм безопасности. 😢

К даггеру и т.д. у меня ровно такие же претензии, если что. Но его рефакторить в разы проще если так уж сложилось и тебе достался такой проект. Синглтон синглтоном погоняет, все вьюмодели приложения перечисленные в одном файле, AppComponent на тысячи строк и всё в таком духе – это прям база.

А если копнуть глубже? На первую строчку документации Why Koin?Koin provides an easy and efficient way to incorporate dependency injection into any Kotlin application.
Знаете что ещё даёт лёгкий и эффективный способ инжектить зависимости? Параметры в конструкторах. В голом котлине. Без всяких DSL и smart API. 🤭

Кстати, у нас на рабочем проекте Koin. Мы за два последних года ни разу туда не сунулись что-то серьёзно переделывать, потому что себе дороже. А если начинаешь проект с нуля и можешь себе позволить использовать конструкторы – нет ни одной причины тащить к себе этот кошмар. Заведи, блин, object со всеми зависимостями, и то лучше будет.

240 0 3 23 13

Forward from: BeeTech
Присоединяйтесь к митапу для Android-разработчиков!

📅 Дата: 07.02, 17:00
📍 Место: DAR U, Коктем-2, 22, 4 этаж

В конце следующей недели мы собираемся с Android-разработчиками, чтобы обсудить оптимизацию процесс в разработке Android-приложений.

Программа митапа:
"Генерация Compose кода с помощью AI" — Алексей Утепов, Android-разработчик, QazCode
"Релизы в InDrive: как не сойти с рельсов" — Илья Гуля, Developer Productivity Engineer, InDrive
"Кастомный DownloadManager в приложении Darlean" — Чингис Богдатов, Android-разработчик, DAR Tech

🔴 Места ограничены! Рекомендуем зарегистрироваться заранее. Переходите по ссылке, заполняйте форму и ждите подтверждения на свою почту. Если вы не получите письмо, значит, места уже заняты.

Будем рады увидеть вас на митапе! ✌🏽


Организуем первый андроид митап от компании. Кто в Алмате заходите, стараемся сделать интересно)


Как быть продвинутым пользователем ПК

Я довольно часто упоминаю свой тезис, что современным софтом сейчас можно пользоваться, только если ты сам разработчик или тестировщик. Потому что любой нормальный человек, не задумывающийся о том, как этот софт работает под капотом, обречён словить все непродуманные корнеркейсы по своему клиентскому пути.

Ну то есть мы как разработчики прикладываем, конечно, все свои силы, чтобы они в наших приложениях были покрыты. Но мы живём в мире, где уже есть миллионы приложений, а там всё плохо. Да и у нас всё плохо, несмотря на то, что мы стараемся. Корнеркейсы это прерогатива сильных и богатых, а все остальные на них подзабивают из-за нехватки ресурсов или компетенций. 🎲

Понятно, что если ты каждый день пользуешься какой-нибудь андроид студией, то все баги уже знаешь вдоль и поперёк. Можно позволить себе с рабочим инструментом немного времени на то, как он работает. Но в среднем мы, а тем более наши обычные родственники и друзья, проводим больше времени на каких-то рандомных сайтах, в каких-то приложениях, куда заходим сделать какую-то одну конкретную задачу. По этому пути ты обычно по ощущениям идёшь и как сапёр пытаешься не подорваться. Чем дальше заходишь по этой воронке, тем страшнее жать каждую следующую кнопку. 💥

Сформулировал для себя основное правило пользования, которое сильно снижает вероятность проблем. Оно абсолютно банальное. Не жать ничего пока идёт какая-то загрузка или где-то крутится лоадер. Даже если не крутится, то лучше у себя в голове немножко троттлить и делать всё с задержкой, а то вдруг на самом деле грузилось, просто забыло тебе об этом сказать. Под это же правило подходит не жать всё несколько раз подряд, как любят QA.

Или обобщённо: перед выполнением любого действия нужно убедиться в том, что состояние системы стабильное, а не временное. Иначе рискуешь быть пользователем, чей сценарий никто не тестировал.




Про ключи в Lazy лэйаутах Compose

Кажется, все уже знают, что в каком-нибудь LazyColumn можно элементам задавать ключи и они используются, чтобы один и тот же композабл лишний раз не теребить. Выглядит примерно так:


LazyColumn {
items(items, key = { it.id }) {
ListItem(it.text)
}
}


Когда мы хотим сюда добавить какой-то хедер возникает абсолютно естественное желание по аналогии написать вот так:


LazyColumn {
item(key = { "header" }) { Header() }
items(items, key = { item -> item.id }) {
ListItem(it.text)
}
}


Собирается, запускается, работает. И потом крашится в проде. 😮

Наблюдаем за прелестями композного API. Вот функция items (упрощённая):


fun LazyListScope.items(
items: List,
key: ((T) -> Any)? = null,
contentType: (T) -> Any? = { null },
itemContent: @Composable LazyItemScope.(T) -> Unit
)


А вот один item:


fun item(
key: Any? = null,
contentType: Any? = null,
content: @Composable LazyItemScope.() -> Unit
)


И в том и в другом случае мы можем передать в key лямбду, потому что у ребят из гугла тут Any? в параметрах. Почему бы нет. И только в комментарии рядом с функцией осторожно написано, что key под капотом на андроиде будет сохраняться в Bundle, поэтому он должен быть или примитивным, или строкой, или Parcelable. А в случае с items - всё тоже самое актуально для key().

Соответственно тут нужно быть офигенно осторожным и помнить что писать надо так:


LazyColumn {
item(key = "header") { Header() }
items(items, key = { item -> item.id }) {
ListItem(it.text)
}
}


Если бы я писал функцию item, то я бы перегрузил её для всех сохраняемых в бандл типов, наверно. Или вообще явную Parcelable обёртку для ключа сделал, её же и в лямбде для items возвращал.

Это вот тот самый кейс за который вас по рукам на код-ревью бьют за Any? где не нужно. Подозреваю, что они таким лайфхаком решали проблему зависимости от Android SDK в foundation, но от этого не проще, честно говоря.


Про поиск

Иногда делаю осторожные вылазки из гуглового мира, чтобы посмотреть, что там вообще у конкурентов. И если для части сервисов в принципе можно найти приятную альтернативу, то поиск для меня последние лет пятнадцать вообще был незаменим. Но с очеловечиванием гугла, уходом от гиковости и постоянным желанием коммерциализировать всё что можно он откровенно становится хуже и хуже. Как вы понимаете, очередной заход. 🔭

Предыдущие были несколько лет назад больше в формате подготовки к судному дню. Что-то меня триггерило и я шёл переключаться на какой-нибудь DuckDuckGo, который как выглядел, так и выглядит таким линуксом из мира поисковиков. Ну то есть нормально ничего не искал, зато весь в белом пальто такой независимый. Пару недель мучался и возвращался обратно.

С приходом нейронок все юзкейсы для поисковой системы делятся у меня в голове на две части. Во-первых, иногда хочется просто наивный тупой поиск. Во-вторых, иногда хочется задать человеческий вопрос. И у гугла удивительно плохо и с первым и со вторым. Я с одной стороны практически не контролирую его выдачу, из раза в раз наблюдаю кучу рекламы, бесполезных виджетов. С другой стороны на какой-нибудь конкретный вопрос типа "Когда вышел альбом Meteora?" он не отвечает, хоть и в результатах поиска ответ явно можно найти.

Какие варианты? Очевидно, без яндексов, бингов и подобных.

Perplexity пытается порвать все шаблоны как поиск должен выглядеть. У него просто чат интерфейс, но с ссылками на источники, которые подтверждают, что он не галлюцинирует. И с одной стороны идея то прикольная, он закрывает второй юзкейс полностью, но выглядит как какой-то страшный комбайн, не оставляя буквально ничего из классического поиска, к которому мы годами привыкали. Copilot от Microsoft примерно тоже самое, хотя и не такой монстр визуально. Мне не заходит, да и первый юзкейс кто решать будет?

Brave Search выглядит как сервис для нормальных людей. Симпатичный, выдача неплохая, умеет в AI вопросы перенаправлять. Но не всегда отвечает на нормально поставленный вопросы, несёт бред, плюс с русским языком всё сильно сложнее. Тем, кто привык к классическому гугловому поиску вполне может зайти. К слову, DuckDuckGo тоже получше стал, чем был. Наверно всё то же самое я и про него могу сказать, хотя в последнее время жить с ним не пытался.

Неожиданно для себя сейчас я остановился на Kagi. Его главный недостаток в том, что он платный. Я теперь плачу ещё и за поиск в интернете, да. Оправдываются они тем, что в отличие от всех остальных он не монетизируется через рекламу. Но он в целом настолько классный, что им хочется продолжать пользоваться и в принципе поддержать продукт. Он закрывает оба юзкейса просто прекрасно.

По умолчанию это максимально олдовый интерфейс с поисковой строкой без лишнего мусора. И если ты хочешь просто что-то поискать, то он просто это находит. Если ты понимаешь в процессе что хочешь задать вопрос нейронке, то просто ставишь в конце вопросительный знак. Офигенно удобно.

В зависимости от уровня твоей испорченности гиковости можно и покастомизировать внешний вид переключалками, и кастомную CSS тему написать, и управлять всем с клавиатуры, и использовать классические операторы для поиска типа кавычек и минусов, и ранжирование разных сайтов в выдаче подкрутить под свои нужды.

Из интересного есть ещё, например, суммаризатор. Можно и в выдаче быстро саммари страницы нарисовать, и чат по её поводу продолжить. С точки зрения UX всё нравится, непонятно о чём ещё мечтать. 💳

В общем, пока прям кайфую и не совсем понимаю почему я могу захотеть обратно. Но будем наблюдать.


Итоги, да. Сам уже успел устать от этого всего.

Во многом настроение отсутствует из-за какой-то крайне неприятной простуды, от которой я вторую неделю не могу нормально отойти. Даже мозг функционирует с какими-то перебоями. Никогда не замечал раньше, чтобы он настолько тупил как сейчас во время болезни. И это вполне подытоживает весь 24 год. По ощущениям на конец – год был фиговенький, если не сказать больше, но мы продолжаем сопротивляться. Попробую вспомнить о чём-то хорошем.

На работе замедление взрывного развития уже воспринимается как что-то негативное. Хотя это и логичный итог того, что мы просто зафиксировались на хорошем уровне, многие почувствовали уверенность и стали брать в работу большие проекты, которые, конечно, затягиваются и воспринимаются в моменте как рутина без видимого результата. Здесь отметим осторожный оптимизм и надежду, что парочка долгостроев таки доберётся до прода в ближайшие месяцы и будет чем пофлексить. Ну и у самого на этом фоне много мыслей и выводов, которыми не терпится поделиться.

Параллельно в этом году для меня главное достижение это социализация. Выступил на двух крупнейших айтишных конфах в Казахстане, нашем Beetech и не нашем Kolesa Conf. Вернулся к Podlodka Android Crew, внезапно для себя даже в роли спикера разок. Ну и нельзя не отметить наши офлайн сходки нейронки пати nullptr.party, шатаут Илье, Ване и многим другим, кто в них принимал участие. Во многом благодаря ним в этом году получилось засинхронить своё восприятие окружающего мира с реальностью, познакомиться с массой людей.

Но это всё айтишное. Всё таки канал тут назван моим именем, а не конкретными технологиями. Хочется разбавить чем-то из нормальной жизни, майлстоуны из которой обычно в инсте. Меньше десятка посещённых концертов и фестивалей в год для человека, который привык их считать десятками – это что-то совсем новое. Хотя были хорошие, запишем в такие Тринадцать карат, Хадн Дадн, Green Apelsin, Аигел и Тени свободы. Впрочем в следующем году есть планы вернуться в большую игру как в лучшие годы.

Но музыки в этом году, кстати, без концертов меньше не стало, стало больше. Догоняю год, наполняю плейлисты и формирую у себя в голове итоги года с самым любимым, поделюсь. Научились довольно стабильно превращать эти свои знания в победы на музыкальных пабквизах по всякому року. Это наверно можно записать как хобби года, хоть и начали ещё в прошлом. Тоже довольно приятная тусовка буквально на глазах организовалась. Удивительно, что буквально любое твоё маргинальное увлечение в наше время может работать и во что-то конвертироваться. Как минимум в какие-то эмоции.

Покупка года, безусловно, Steam Deck. Настолько восхитительного устройства в пересчёте на деньги я в руках не держал никогда. Мне кажется мы вообще настолько забыли, что люди могут разрабатывать продукты для людей, что это воспринимается просто невероятно. Valve и технически сделали что-то невозможное со своим протоном, и чисто продуктово, дав нам страшную вариативность что с ним можно делать. Когда ты можешь после работы переткнуть хаб из макбука в дек и запустить под его линуксом условный виндовый Hearthstone на большом экране, со всей работающей периферией и запущенным в параллель дискордом. Это что, блин, за чудо? Почему это вообще работает и почему об этом не кричат на каждом углу?

В вышеупомянутый хартстоун хотелось бы играть поменьше в следующем году, а то это прям стало похоже на зависимость. Чёртов дуо режим, появившийся в этом году. В новом году делаю большую ставку на более агрессивное развитие и надеюсь на собственную смелость, которая поможет порешать множество вопросов.

Вас тут тоже стало в два раза больше, чем годом раньше, чему я очень рад. ✏️

С наступающим! 🎉
Надеюсь год будет ну хоть чуточку лучше, а то сколько вообще можно? 🥂


Нельзя так просто взять и удалить модуль

Нам нужно поговорить серьёзно, вместо того чтобы закрывать на это глаза из раза в раз. Я ведь правильно понимаю, что за всю десятилетнюю историю андроид студии у нас так и не появилось адекватного способа удалить модуль в проекте?

Я специально пошёл запустил Idea и сравнил, чтобы сейчас полнейшим идиотом не показаться. В Android Studio выделяем модуль, нажимаем Delete, происходит ничего. Вообще. В Idea нажимаем Delete – на уровне файлов не происходит ничего, но пропадает значок модуля на папке, после чего повторный Delete удаляет все файлы. ✏️

Чтобы удалить модуль у нас, нужно удалить строчку в settings.gradle, пересихронизироваться и удалить папку. По-моему это самый прямолинейный способ, пользуюсь им все эти годы. Ну или немного сложнее: пойти в проводник, удалить папку там, после чего поправить settings.gradle и пересинхронизироваться по итогам.

Проблема ещё больше, когда мы не про модули говорим, а про какие-то "особенные" папки. Например сорссеты androidTest и test. Там альтернативы вообще как будто нет, я абсолютно во всех случаях иду в проводник удалять.

Пока это пишу, кстати, понял, что есть альтернатива в виде Mark Directory As → Excluded, чтобы IDE перестала держаться за эти файлы и давала удалять. Но это всё равно какое-то абсолютно лишнее действие. Что мешает мне просто удалить все выделенные файлы рекурсивно? Ведь какое-то объяснение наверняка есть. Есть же? Я даже не прошу за меня название модуля из settings.gradle удалять, просто не мешайте мне моими файлами управлять.

Если я вообще в глаза долблюсь, не вижу очевидного и совсем неправ, то ставьте клоуна и помогите мне в комментариях найти решение лучше, я честно не знаю. 🤡

r/mAndroidDev в очередной раз принёс подумать.


Рутина

В последнее время начал замечать, что большая доля моего рабочего времени уходит не столько на какие-то задачи, достижение личных и командных целей, сколько на попытки переварить и осмыслить хаос, который творится вокруг.

И ты такой сидишь, анализируешь импакт от всего этого на кодовую базу, на время сборки, на процессы, на разработчиков, на пользователей. Код ревью в этом контексте вообще мелочь, прямо очень и очень частный пример того, о чём я говорю. Ты буквально как последний рубеж обороны от всего, что может потенциально навредить проекту, но при этом как-то просочилось до твоего уровня. 🔫

Хорошо если это работа в формате предварительного груминга, то есть кто-то проактивно пришёл советоваться. Но чаще всего то кто-то хочет фичу через хотфикс протащить в обход релизного цикла. То какие-то ребята из соседней команды быстренько сделали интеграцию с вашим проектом, от которой у тебя смех и слёзы одновременно. Где-то приносят квартал работы в одном мёрж реквесте с посылом, что им в релиз нужно было вчера. А вон там кто-то решил, что его новый велосипед намного круче того, что используется в проекте последние два года. Примеров десятки, сотни, и все они такие разные, что их не классифицировать, ни тем более автоматизировать не получается.

Самое выматывающее в этом то, что ты прям фултайм придумываешь аргументы, почему так делать не стоит. Встаёшь на позицию инициатора, пытаешься понять его боль, придумать компромиссное решение. И это всё уже когда этим заниматься по логике слишком поздно. 😓

И вот непонятно. Может зря я столько сил на это трачу? Вдруг если я пропущу что-то "опасное" в моей картине мира, то ничего страшного и не случится? Да и если случится то сильно ли большая это проблема? Может я лучше бы чем-то конструктивным занимался вместо этого? С другой стороны, опыт мне говорит, что благодаря таким параноикам, которым не пофиг, проекты в основном держатся и развиваются. Я почти убеждён, что без меня на инерции всё что касается андроид разработки на проекте проехало бы ещё минимум несколько лет. Но вот что развивалось бы такими же темпами я уже сильно не уверен.

Вывод наверно здесь будет такой, что эту роль нужно по чуть-чуть на всю команду раскидывать. Чтобы не ты был последней инстанцией, а любой разраб имел полное право продавить нашу общую позицию. Ну и то, что эту общую позицию надо достаточно явно где-то фиксировать.


Эффекты и Compose

В эфире регулярная рубрика "в интернете кто-то посрался". Сегодня на повестке дня вот этот обмен твитами. Там всё начинается с будничного хаяния Compose, а потом туда приходит один из разработчиков Compose и тут понеслась.

Ключевые тезисы:
- Эффекты использовать вообще плохая практика
- Наша же документация в этом смысле учит людей плохому, мы пытались донести это деврелам, они не слушают
- Функцию remember тоже лучше не использовать за исключением некоторых юзкейсов типа анимаций. ✏️

И это довольно забавные инсайты. Понятно откуда берётся это желание, чтобы Composable функции были (условно) чистыми, но в жизни по моему это не очень работает, учитывая горы нашего легаси за миром композа.

Плохо, что альтернативы не очень-то и раскрыты. Я покопался в нашей кодовой базе и попытался сформулировать наши юзейсы для эффектов.
- Во-первых они всё равно используются где-то под капотом collectAsState*. Считается ли это плохой практикой я не уверен. Но без этого, кажется, мы вообще не можем в том месте, где пытаемся связать Composable функцию с каким-то логическим компонентом, например вьюмоделькой, буквально по всех популярных подходах к архитектуре.
- Во-вторых это подписки на всякие Flow, т.к. только внутри эффектов у нас есть скоуп. И всё это можно было бы разрулить где-то в тех же логических компонентах, если бы не нужно было на эти события взаимодействовать с UI или платформенными штуками. Где-то у нас всратые Material апишки типа боттомшитов и снэкбаров, которые ни спрятать ни показать в m2 без корутин нельзя. Где-то нужен активити контекст, например, чтобы другую активити открыть. Где-то у нас под листвой вообще грабли в виде AndroidView, с которым нужно общаться императивно. Где-то приходится заворачивать в это всё пермишны и Result API. И как быть без эффектов то?
- В-третьих это часто используется как колбэк от UI, что он там начал рисоваться, типа "бизнес логика, запускайся". В этом кейсе я согласен, можно это на уровень Composable и не тянуть. С remember я тоже по большей части согласен в продуктовом коде, но когда пишем библиотеку уже не очень. Ребята в аккомпанисте соврать не дадут.

В общем типичный срач между тем, кто пишет инструмент и предполагает как его нужно использовать, и теми кто пытается применить его на практике и борется со всем миром лишь бы оно вообще завелось, и пофиг на то насколько это идеологически чисто. Можно понять обе стороны, но обе не сильно-то и правы. Мы понимаем, что это всё лучше не использовать, если можно обойтись. Нам тоже хотелось бы писать такие Composable функции, которые просто принимали бы уже готовый стейт. Но это невозможно, или с точки зрения существующих библиотек (от других отделов гугла же), или с точки зрения легаси, или с точки зрения перформанса, или просто альтернатива настолько бойлерплейтная, что всему комьюнити проще так.


Forward from: CodeTalks_Алматы
🍿Записи докладов с CodeTalks на сайте.

Заходите на страницу нужного вам спикера и наслаждайтесь. Чтобы смотреть на сайте нужно залогиниться.

Приятного просмотра - https://2024.codetalks.kz/#sections

После просмотра оставляйте ваши отзывы спикерам. Ещё собираем, спикерам важен ваш фидбек❤️


Респект таким конфам, которые выкладывают записи не через полгода, а сразу, пока ещё не забыл, что хотел посмотреть. Да ещё чаще звук на видео лучше, чем в жизни был. Ставим лайк 👍

upd. меня поправляют, что видео доступны только купившим билеты, ну штош, такие тоже тут есть :)


CodeTalks 2024

Насыщенный выдался вчерашний день. С самого утра и до вечера провёл его на конференции CodeTalks.

Кейноут от Виталия Шароватова – такой типичный кейноут. Мотивационно-заряжающий. По сути, конечно, ничего нового не сказано, но достаточно ёмко сформулировано то, что и так всем известно. Послушали про то, что нужно качать технические скиллы и социальный капитал. Это довольно прикольная находка на первом же докладе дня рассказать людям, что вы сюда пришли общаться, поэтому общайтесь, с аргументами. Забегая вперёд, благодаря этому или нет, но на этой конфе действительно все легко шли на контакт, благодаря чему всё прошло прям кайфово. Коллегам по экс-мобайл бродкасту (хехе) тоже спасибо за компанию.

Дальше по отзывам от других людей были интересные доклады, которые в записи, может быть, даже переслушаю. Обещают видео на неделе. Но на самой площадке время докладов – это самое удобное время сбора мерча со стендов компаний и еды со столов кейтеринга. Пока людей не так много – даже можно как-то вздохнуть спокойно, а то в последнее время за моду взяли проводить конфы в помещениях, где холлы явно не рассчитаны на такое количество людей. Кинотеатр Арман, в котором всё проходило, сам по себе прекресен как памятник архитектуры, красиво, залы потрясающе удобные засчёт тишины и мягкости кресел, но вот именно холла немного не хватало.

Сказал про тихие киношные залы, надо сказать и про громкий холл. Очень неудачное решение там в уголке проводить трек квартирников, шумно, ничего не слышно, но посыл "делайте правильно, неправильно не делайте" от всех посещённых квартирников у меня считался. Отмечу дизайнерский про UX, там достаточно классное живое обсуждение было.

Мобильных докладов было буквально три. Виталий Маркус рассказал интересные практические штуки об оптимизации производительности на Compose без вот этой всей банальщины про Stable классы, с реальными примерами из приложения Flo. Продуктивно пообщались и после сессии о том, почему гугл нас из коробки своими апишками не заставляет писать оптимизированный код.

Доклад Сергея Лапина из Vivid Money для меня стал самым неожиданно интересным, потому что из названия мне было сложно предположить, что он в итоге окажется про Compose Multiplatform Wasm тулзу для маркетологов, в которой они могут подготовить свои баннерные кампании видя в реальном времени как это будет выглядеть, так как переиспользует дизайн-систему приложения. Это звучит как чуть ли не первый классный юзкейс как в работе применить эти ваши хайповые мультиплатформы. Но даже и этот кейс скорее личная инициатива и из-за такого маргинального стека может и не выжить после увольнения инициатора)

Ну и под конец этот андроидный "трек" разбавил Санатжан Аймухамбетов из Колёс с иосным докладом про то, каких фич они накидали себе в обновлённое дебаг-меню. Почерпнул чуть-чуть идей, но меня почему-то не покидает ощущение, что многие задачи, вынесенные в неё, у нас решаются какими-то готовыми инструментами или вообще для нас не имеют смысла.

За организацию суперлайк, еда весь день была и не кончалась, задержек никаких не было, хорошая коммуникация от организаторов, удобные параллельные часовые слоты под доклады, привезённые из заграниц спикеры. Единственное что, мне показалось – спикеров не очень сильно гоняли, у многих были какие-то косячки и не самая чёткая речь. Афтерпати на всех в соседнем баре с некончающимся за 3 часа пивом и закусками это тоже что-то новое. Короче, явно знали, что делали, и явно деньги не проблема. Вопрос "за чей счёт банкет" не даёт мне покоя до сих пор. Ну не верю я, что с недорогих билетов и нескольких спонсоров это окупается, спасибо вам, если что 🙂


Документация не для людей

Главная проблема любых LLM сейчас в том, что у нас человеков в голове с огромным трудом формируется связь между задачей и тем, что её можно делегировать нейронке. То есть они уже могут очень очень много всего делать как минимум нормально, но мы по старинке это делаем сами, т.к. не задумываемся об этом. А когда задумываемся, то удивляемся почему раньше не думали. 🤔

Довольно много в последнее время играюсь с Projects у Claude. Это примерно тоже самое что и кастомные GPTs у ChatGPT. То есть мы заранее можем начинать чат с определённым контекстом "проекта", причём в этот контекст мы можем накинуть и кучу файлов в качестве базы знаний и системные промпты.

У нас в репе проекта есть совсем небольшая маркдаун документация, которая писалась в первую очередь как материалы для онбординга. Или для новых разрабов, или для старых в новую технологию / новый подход, но всё таки для онбординга. Есть техрадар, где описана актуальность всех технологий, есть документация по подходу к модуляризации с типами модулей и правилами, есть документация по архитектуре конкретных фич, есть небольшой роадмап типа от чего избавляемся и куда хотим двигаться. А кроме документации, понятное дело, наш проект очень хорошо описывают файл Version Catalog и конфиг с detekt правилами. То есть всё то, от чего код сильно зависит.

Люди документацию редко читают превентивно. Для людей документация - это просто место куда можно сходить за дополнительной информацией в случае проблемы. А вот нейронка нет, это просто восхитительный материал для помощи ей. Закидываем это всё в кастомный Project, и любой чат сразу начинается без необходимости расписывать огромный промпт с деталями как делать, как не делать, что тебе надо, и так далее. Мы буквально онбордим нейронку заранее и один раз. И это у меня ещё где-то 15% от потенциального размера контекста, можно представить сколько туда ещё можно добавить всего.

Так вот, это вообще геймченджер. Сейчас мы на том этапе, где клод в новом чате сразу может по одному скриншоту написать композ вёрстку экрана и всю архитектурную обвязку именно так как это написано в нашей доке. А самый большой прорыв этого всего с технической стороны заключается в том, что этот код после копипаста в студию сразу зелёный, в большинстве случаев не приходится исправлять ничего. Всё таки замечу, что код тут довольно шаблонный, там где надо что-то красивое придумать - всё ещё не так радужно.

В связи этим опытом у меня даже какой-то концептуальный сдвиг в голове произошёл. Всем понятно, что промпт инжинеринг невроятно важен и всем будет нужен, но эта мысль куда-то на шаг дальше ушла. А я теперь почти уверен, что документацию мы будем писать не людям, а нейронкам в первую очередь, потому что им она сильно нужнее и импакт от такой документации в разы больше. И финальная мысль - нам нужно инвестировать больше времени в то, чтобы в тексте формализовать все устные соглашения. То что разработчики будут их игнорить нас даже не волнует, потому что всё равно есть понятный юзкейс.

PS. GPTs у ChatGPT даже не близко в этом смысле, видимо из-за ограничений по размеру контекста он не воспринимает файлы из knowledge base как этот самый контекст. Ответить про содержимое этих файлов может, но когда просишь сделать фичу как принято по документации - он просто на это всё забивает и пишет максимально дженерик код в гугловом стиле и льёт кучу воды вместо того, чтобы почти молча написать код.

PPS. Купил стимдек, количество постов резко сократилось до тех пор, пока не пройдёт зависимость и снова не появится свободное время, сами понимаете. 👮


Clean / Rebuild Project

В новой канарейке студии удалили пункты меню Build - Clean и Build - Rebuild Project. Ага, две самые тыкаемые кнопки студии после Invalidate Caches and Restart удалили, вы правильно поняли. 💥

И узнаём мы об этом конечно из постов в r/mAndroidDev, потому что в ченджлоге студии изменения в меню Build упоминаются, но именно про это там нет. Там говорят, что в общем доработки скорее направлены на то, чтобы все эти задачи запускались только на выбранной конфигурации, а не на всём проекте целиком.

Мысль придумать с этим что-то довольно похвальная, т.к. мало кто из разработчиков вообще задумывается насколько ребилд всех source-сетов это оверкилл для проблемы, которую они пытаются решать. Но они удалили и не дали никакую замену. Через общий поиск найти всё ещё можно, но в менюшке больше нет.

Пункт Clean всегда делал gradle clean в корне, если не ошибаюсь, т.е. удаляла результаты сборки во всех подмодулях. Ну да, зацепит лишние модули, если в текущей конфигурации они не используются, но обычно это не настолько долго. А действия гугла сейчас явно направлены на то, чтобы не показывать нам что там вообще под капотом есть какой-то грэдл.

Моя претензия к этому пункту в таком случае заключалась бы только в том, что его бывает недостаточно. Хочется какой-то диалог с разными уровнями зачистки, от кэша конкретных модулей до кэша самого грэдла и на уровне проекта и на уровне GRADLE_HOME. Но теперь у нас даже этого нет.

Rebuild Project делал gradle clean build, в котором build это слииишком общая таска, объединяющая всё на свете. Это действительно пункт довольно бесполезный, но вместо него обывателю хотелось бы видеть что-то типа gradle clean + сборка только выбранной конфигурации, без пересборки тестов, всех билдвариантов и всего такого.

Если же мы пофантазируем про какие-то полезные юзкейсы, которых не хватает в смысле сокрытия от нас грэдла, то хочется какой-то быстрый способ флажок --rerun-tasks докинуть, или --refresh-dependencies. А такого тоже нет.

Сколько раз эти кнопки спасали нас от какой-то нестриггерившейся кодогенерации, от рандомных багов при переходе между ветками, от кучи других проблем. Да и не то чтобы оверхед настолько критичен на большинстве проектов. А теперь видимо всем учиться делать ctrl+ctrl+вручную вызывать грэдл таски или как взрослые через терминал. Удачи новичкам.

PS. Обновился на Ladybug через Toolbox, частично слетели настройки. Обычный день. 😷


18 октября. Kolesa Conf '24

Цель в жизни на какое-то время пропала, выступил вчера у колёс на конфе. Стоять в расписании первым должно было быть довольно стрессово, но по факту кажется, что это очень выгодное положение. Люди только пришли на конфу, зашли и заполнили все места, никто не шатается через дверь туда-сюда, никто ещё не отвлекается на другие активности, все делают вид, что пришли ради докладов. Ну и плюс я сам, понервничал первые полчаса конфы, а дальше на спокойничах, только сразу уставший.

Впрочем, в этот раз, в отличие от предыдущих выступлений я не сильно то и переживал. Аудитория для мобильного трека была поменьше, чем предыдущие площадки инженерных треков типа девфеста или битеха, поэтому воспринималось спокойнее. Да и уверенности в себе было побольше, честно говоря. Отдельно хочется отметить головные микрофоны, первый раз выступал в таком, вообще кайф, с ручным всегда нужно помнить как его держать, это лишние силы отнимает, да от человека к человеку всё сильно плавает.

На своё удивление первый раз за все прогоны идеально уложился в тайминг. Это чудо происходит каждый раз именно на самой площадке, но никак не дома. По своей речи и презе в целом доволен, точно лучшие из всех моих, впрочем я на них и времени по итогу потратил очень много. Сам уже устал от темы, от презы, от её оформления. Явный признак того, что передержал.

Если сравнивать, то выступать мне понравилось больше тут, доклады понравились больше тут, чисто мобильный трек это прекрасная редкость. Когда тебя слушает почти сотня чистых мобильщиков это другой уровень. Но с точки зрения организации мне больше понравился наш битех. Универские актовые и лекционные залы очевидно больше подходят для выступлений, чем банкетный комплекс. Выглядит дорого-богато, с замшей и вензелями, но не очень удобно. Техника на других докладах чуть подводила, из-за одноуровневости рядов стульев не всегда было видно экраны за головами сидящих, очередь на входе к началу из-за которой не все успели зайти к первым докладам. Да и в целом как будто для полутора тысяч посетителей площадка слишком мелковата. Это из минусов.

Так или иначе, большущая благодарность организаторам за проведение конфы, и за то что дали возможность выступить в клёвом лайнапе. И ещё респект всем коллегам из билайна, кто пришёл поддержать даже не всегда понимая контент. Всем, кто подписался сюда после доклада привет! ❤️

А про доклады вот у Вани почитайте. Я на несколько часов после своего отвалился на всякие обсуждения в экспертных зонах и чил.

PS. Общая афтерпати немного скудноватая вышла, что впрочем не помешало наконец-то спокойно пообщаться. А до спикерской я, к сожалению или счастью, не дожил)
Видео и фотки обещают скоро. Живую фоточку с собой украл из местного мобайл бродкаста, других пока нет.

🔗 Презентация


Video is unavailable for watching
Show in Telegram
Гугл вчера раскатил обновлённый дизайн в консоли. И это какой-то позор. Давайте посмотрим на новое боковое меню.

Первое и самое прекрасное в нём – на ховер теперь стабильно появляется скроллбар, из-за которого доступная контенту ширина уменьшается. Для понимания, этот блок фиксированный, динамически ширину у него менять нельзя,. Когда размер контента меняется для текста не всегда хватает места и некоторые пункты начинают переноситься. Это спишем на длинность слов в русском языке, в английском ведь такого нет. Открытые в соседних окнах гитлаб и телеграм ведут себя абсолютно адекватно.

Вторая проблема в полнейшей неконсистентности всех этих пунктов. Верхние – самые важные по их логике. Они по умолчанию фона не имеют, цвет текста и иконок серый, при выделении фон превращается в скруглённый с правой стороны синий прямоугольник. Ниже вы такого уже нигде не увидите.

Пункты ниже это какая-то древовидная структура. Впрочем, на самом верхнем уровне нет никакой стрелочки, которая бы показывала раскрываемость. Поэтому что структура древовидная мы узнаём только опытным путём. И они почему-то изначально синие, как остальные при ховере, а цвет текста и иконок на них почему-то чёрный. При нажатии их цвет фона не меняется вообще, вложенные пункты показываются карточками. Уровнем ниже пункты уже такими карточками не разделены, они просто рисуются с левым отступом с еле еле заметной разделительной линией. Здесь всё на первый взгляд даже выглядит неплохо, но ховер или нажатие на любой из финальных пунктов выделяет ярким цветом верхнюю группу, а конкретный выбранный пункт остаётся на белом фоне с не очень заметным синим текстом.

Ещё до кучи накидаем мелочей, которые к последним изменениям относятся не так сильно. Кнопка "Все приложения" сверху вообще другая. Там и размер иконки и шрифт отличаются, а на ховер внешний вид в отличие от всего остального не меняется вообще. BTW нажатие на хедер Google Play Console делает то же самое, так что отдельная кнопка ещё и бессмысленна.

При нажатии на любой пункт меню, который редиректит на "другую страницу" эффект от клика я вижу только после успешного запроса. Т.е. буквально секунду сидишь и не понимаешь нажалось или нет. Для SPA такое уже выглядит не очень.

Больше одного пункта на любом уровне вложенности раскрыть не дают. Поэтому при любом клике всё остальное закрывается и нужный пункт приходится искать заново.

Обожаю обновления консоли. Каждый второй заход в него за последние 15 лет приходится заново учиться, потому что что-то поменяли. Ладно бы ещё у них в команде там кто-то был, кто перед релизом в прод мог подобный этому фидбек дать. Но нет, фигню делают раз за разом. Причём ведь мы с вами разработчики, понимаем что разное делать дольше и сложнее, чем одинаковое. От этого ещё более абсурдно.

PS. Вайбы анекдота про письмо на спичечный завод. Вы там сумасшедшие что ли все? 🧘


Инициализация в ViewModel

Последний месяц в англоязычном сообществе в очередной раз перетирают тему как правильно триггерить инициализацию стейта в ViewModel. Сначала было обсуждение в твиттере, потом вот здесь по итогам появилась статья, на реддите и в комментариях автору закидали всю панамку, на ютубе ещё раз пережевали, и закончили всё тем, что автор вторую статью написал с ответами (оверинжинеринг лютый) на популярные вопросы. И это всё прям интересно так, показательно.

Задача такая: есть экран, у него есть какое-то состояние, на старте триггерится какой-то процесс, например запрос в интернет, который поменяет это состояние. Вопрос звучит так: где это всё делать? Сразу оговоримся, что речь идёт только про Compose, поэтому зумеры пытаются придумать решение проблеме, которую раньше даже не приходилось решать.

Первое решение, которым, по опросу от автора, пользуется примерно треть: LaunchedEffect(Unit) { viewModel.load() }. То есть Composable функция при первой рекомпозиции сама триггерит вызов какого-то метода. Плюсы: бизнес логика отвязана от создания объекта. Минусы: можно забыть; вьюшка командует вьюмоделью; при пересоздании вьюшки всё перезагрузится.

Второй вариант более популярный - использовать init секцию ViewModel. Плюсы: вызвать инит секцию ты никогда не забудешь. Минусы: бизнес логика (запуск корутины) формально является частью создания объекта и вытекающие из этого последствия.

На это всё пришёл чувак из гугла и говорит: вообще-то и то и это антипаттерны, у нас в документации даны все рекомендации Рекомендации заключаются в том, что состояние экрана должно быть холодным флоу, который запускает всю логику инициализации уже когда вьюшка на него подпишется. Ну и чтобы каждый раз флоу не пересоздавать, то обмазать StateFlow какой-то стратегией типа SharingStarted.WhileSubscribed(5_000). Так, говорят, ещё у наших дедов в LiveData было.

Плюсы: бизнес логика отвязана от создания объекта. Вручную дополнительно делать ничего не нужно. Переживёт смену конфигурации. Минусы: вообще нафиг всё остальное, но мы все вам об этом не расскажем. 🏥

Мне кажется эта строчка с 5 секундами это какой-то мем, потому что на полном серьёзе это в рекомендациях писать не стали бы. Идея заключается в том, что пересоздание вьюшки типа поворотов экрана стейт переживёт, а в случае если на него "долго" никто не подписан, то флоу можно прибить. Надёжная как швейцарские часы. Перешёл на другой экран, через 10 секунд вернулся - всё перезагружается. Аргументируют это тем, что импакт от перезагрузки обычно незначительный. Без комментариев. Даже если весь мир закэшировать, то это всё равно лишняя работа по восстановлению состояния убитого ни за что.

Стейт экрана это что-то более комплексное, чем единожды созданный дата класс. Для загрузки могут понадобиться параметры пришедшие из аргументов экрана или от UI. Возможно мы загрузку захотим зарефрешить каким-нибудь свайпом. Обычно ViewModel апдейтит его из кучи разных методов и это нормально. Возвращаться в 2017 комбинируя все эти потоки данных в одну огромную реактивную цепочку я не очень хочу, я уже привык, что можно вместо этого писать простой код. Как по мне это решение становится хуже и хуже с каждым маленьким усложнением.

Справедливости ради, если мы хотим что-то подобное без этих недостатков, то кроме WhileSubscribed есть стратегии SharingStarted.Lazily или Eagerly. К ним у меня вопросов уже сильно меньше, вот хорошая статья с похожими мыслями, они хотя бы UX не ломают. Да даже и в документации гугла по ссылкам выше это сказано, но почему-то на виду примеры кода только с первым. 😱

А вы как подобное пишете? Мне init + MutableStateFlow проще и понятнее вообще всегда. Стреляло в ногу один раз, но это уже отдельная история.

20 last posts shown.