Что выведет этот код?
Anonymous Quiz
6%
bar(x=42, y=0)
1%
bar(x=42, y=0.0)
21%
bar(x=42)
26%
bar()
45%
Не скомпилируется: "Overload resolution ambiguity"
Ого, в Android Gradle Plugin 8.5.0 оказывается наконец завезли поддержку test fixtures, для модулей на Kotlin. Пока что нужно включать экспериментальный флаг.
Release notes для версии 8.5.0 почему-то пустые, так что узнают только те, кому повезло :D
Test fixtures — любые "приспособления" для применения в тестах. Это могут быть тестовые реализации сущностей, генераторы тестовых данных, специфичные для тестового фреймворка вещи и т.д. В Gradle можно применить плагин test-fixtures к модулю и тогда весь код из source set'а с названием
Так вот, раньше в обычных Kotlin проектах test fixtures работали, в Android + Java тоже, а в Android + Kotlin — нет.
#agp
Release notes для версии 8.5.0 почему-то пустые, так что узнают только те, кому повезло :D
Test fixtures — любые "приспособления" для применения в тестах. Это могут быть тестовые реализации сущностей, генераторы тестовых данных, специфичные для тестового фреймворка вещи и т.д. В Gradle можно применить плагин test-fixtures к модулю и тогда весь код из source set'а с названием
testFixtures
будет доступен в тестах этого модуля и для подключения в тесты других модулей. Если у вас есть и Instrumentation, и Unit-тесты, в testFixtures
можно сложить общий код. Как и в тестах, в test fixtures доступны internal-сущности из модуля. Так вот, раньше в обычных Kotlin проектах test fixtures работали, в Android + Java тоже, а в Android + Kotlin — нет.
#agp
Где-то лет пять я пользуюсь fixup'ом через IDE, чтобы добавлять изменения к коммитам из истории, и за это время смирился, что эта фича работает странно. Она просто создаёт коммит, но не ребейзит его автоматически, и приходится через интерактивный ребейз двигать коммит и делать fixup руками. Даже в консольном гите удобнее, там можно при ребейзе указать флаг
И вот спустя годы, когда в очередной раз пригорело от поведения fixup, я решил найти этот баг в YouTrack чтобы влепить звезду. Нашел. И оказалось, что можно было не страдать. Просто IDE учитывает настройку гита
В комментариях к issue можно наблюдать знатное полыхание на тему "а как я об этом должен был узнать?" и я полностью согласен.
Есть ещё одна ловушка с этой фичей. При коммите нужно обязательно нажать "Commit and Rebase", который спрятан внутри выпадающего списка около кнопки "Commit", иначе магии не произойдёт. Про это, кстати, есть отдельная issue.
👆 TL;DR
Чтобы в IDE не двигать руками коммиты с префиксами
#git #idea
--autosquash
и все коммиты с префиксом fixup!
или squash!
сами посквошатся как надо. Ну то есть явно какой-то баг в IDE, иначе кнопка "Fixup" почти ничем не отличается от "Interactively Rebase from Here".И вот спустя годы, когда в очередной раз пригорело от поведения fixup, я решил найти этот баг в YouTrack чтобы влепить звезду. Нашел. И оказалось, что можно было не страдать. Просто IDE учитывает настройку гита
rebase.autosquash
и если её выставить в true
, всё начинает работать как надо 🫠В комментариях к issue можно наблюдать знатное полыхание на тему "а как я об этом должен был узнать?" и я полностью согласен.
Есть ещё одна ловушка с этой фичей. При коммите нужно обязательно нажать "Commit and Rebase", который спрятан внутри выпадающего списка около кнопки "Commit", иначе магии не произойдёт. Про это, кстати, есть отдельная issue.
👆 TL;DR
Чтобы в IDE не двигать руками коммиты с префиксами
fixup!
и squash!
в нужное место при ребейзе, включи настройку rebase.autosquash
:git config --global rebase.autosquash true
#git #idea
Штош. До свидания Android, может ещё встретимся
Андрей Бреслав, Роман Елизаров, Дмитрий Жемеров, Светлана Исакова и другие причастные к созданию языка полтора часа рассказывают как это было. Интересно, что заход Kotlin в Android по сути был случайным и мобильные разработчики вообще не были целевой аудиторией :)
(Да, я знаю, что это Telegram, а не Twitter :D)
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Beyond The Success Of Kotlin / The Documentary by EngX
Almost 15 years ago, a small engineering team at JetBrains embarked on what seemed like a crazy endeavor — to create their own programming language and succeed with it. In the early 2010s, Java was one of the most popular languages, used by millions of engineers.…
Я считаю, что в релизной версии приложения нужно оставлять логи, и сейчас я вам докажу это на примере из жизни.
Недавно я стал клиентом Generali Srbija (страховая компания) и пользователем их замечательного мобильного приложения. Зарегистрировался, авторизовался и... приложение моментально закрывается когда я его открываю.
Первая догадка — возможно приложению не понравилось, что я отклонил все запросы пермишенов, включая доступ к микрофону, совершению звонков и контактам. Это оказалось ни при чём. Тогда я решил проверить есть ли что-то полезное в logcat (см. скриншот). Логи, которые выводят мой токен, хэш пароля и персональные данные, а так же сообщения типа "Я тут" пропускаем. В конце видим, что приложение само вызывает
Дальше остаётся только декомпилировать APK через APKTool и поиском найти нужное сообщение лога. Отгадка оказалась простой — если у пользователя обнаружен root, приложение просто закрывается. Кто-то скажет, что это не user-friendly решение, но я парирую цитатой одного мудрого разработчика: "Пользователь всё равно найдёт как сломать приложение, поэтому мы решили не обрабатывать краевые сценарии".
А теперь представьте как было бы сложно понять что происходит, если бы не было никаких логов, приложение бы закрывалось не через
Ещё один вывод — если вы ищете работу в Сербии, Generali Srbija отчаянно нуждаются в разработчиках, просто пока этого не поняли.
#security
Недавно я стал клиентом Generali Srbija (страховая компания) и пользователем их замечательного мобильного приложения. Зарегистрировался, авторизовался и... приложение моментально закрывается когда я его открываю.
Первая догадка — возможно приложению не понравилось, что я отклонил все запросы пермишенов, включая доступ к микрофону, совершению звонков и контактам. Это оказалось ни при чём. Тогда я решил проверить есть ли что-то полезное в logcat (см. скриншот). Логи, которые выводят мой токен, хэш пароля и персональные данные, а так же сообщения типа "Я тут" пропускаем. В конце видим, что приложение само вызывает
System.exit(0)
, написав перед этим "Это настоящая загрузка".Дальше остаётся только декомпилировать APK через APKTool и поиском найти нужное сообщение лога. Отгадка оказалась простой — если у пользователя обнаружен root, приложение просто закрывается. Кто-то скажет, что это не user-friendly решение, но я парирую цитатой одного мудрого разработчика: "Пользователь всё равно найдёт как сломать приложение, поэтому мы решили не обрабатывать краевые сценарии".
А теперь представьте как было бы сложно понять что происходит, если бы не было никаких логов, приложение бы закрывалось не через
System.exit
и была включена обфускация! Поэтому если вы не уверены в стабильности приложения, оставляйте логи и отключайте обфускацию. Так пользователи смогут сами подебажить приложение и отправить вам на почту результаты своего исследования, останется только пофискить. Можно было бы ещё флаг debuggable=true
выставить, но Google Play такое не пропустит ☹️Ещё один вывод — если вы ищете работу в Сербии, Generali Srbija отчаянно нуждаются в разработчиках, просто пока этого не поняли.
#security
В общем, я ВНЕЗАПНО понял, что уже вообще-то почти декабрь, а значить вот-вот начнётся новый Advent of Code. Забираю обратно все свои подтрунивания над коммунальными службами, которые "не были готовы к зиме". Я тоже не был готов.
Для новых подписчиков – я уже третий год организую "клуб решал Advent of Code" и мы 25 дней решаем задачи истрадаем получаем положительные эмоции. В этом году организацию начал очень поздно, так что скорее всего состав решающих будет достаточно камерный :)
Заходите в канал @aoc_club и зовите друзей!
Для новых подписчиков – я уже третий год организую "клуб решал Advent of Code" и мы 25 дней решаем задачи и
Заходите в канал @aoc_club и зовите друзей!
Forwarded from Advent of Code Club (Osip Fatkullin)
Please open Telegram to view this post
VIEW IN TELEGRAM
Этого ещё никто не видел, вы первые 👀
Теперь принятие архитектурных решени и проектирование нового функционала для Ktor происходит публично в репозитории ktor-klip!
Первый KLIP на очереди – официальное решение для DI. Все желающие могут посмотреть какой планируется дизайн и повлиять на него на ранней стадии!
Если вы используете Ktor в качестве клиента, эти изменения пока никак вас не коснутся, они направлены на то чтобы упростить использование DI при написании серверов.
А здесь в комментариях можно похоливарить про "зачем ещё один DI?", "почему не Koin?", "будет compile-time валидация графа?". Хотя если прочитать документ, это вопросы отвалятся 😀
#ktor
Теперь принятие архитектурных решени и проектирование нового функционала для Ktor происходит публично в репозитории ktor-klip!
Первый KLIP на очереди – официальное решение для DI. Все желающие могут посмотреть какой планируется дизайн и повлиять на него на ранней стадии!
Если вы используете Ktor в качестве клиента, эти изменения пока никак вас не коснутся, они направлены на то чтобы упростить использование DI при написании серверов.
А здесь в комментариях можно похоливарить про "зачем ещё один DI?", "почему не Koin?", "будет compile-time валидация графа?". Хотя если прочитать документ, это вопросы отвалятся 😀
#ktor
Пробежавшись по постам за год я понял, что безнадёжно отстаю от трендов. Во-первых я ни разу не поругал дядюшку Боба, а во-вторых ни разу не бомбил про Gradle (предупреждение о сломанном релизе не в счёт). Негоже уходить в новый год с такими пробелами, поэтому буду исправляться. Хотя бы частично.
С дядюшкой Бобом и без меня неплохо справляются, я бы мог разве что на его стороне выступить, но это не модно. А про Gradle мне есть что сказать. Если у вас в этот момент возникла мысль "прочитаю лучше после праздников", подумайте, хотите ли вы начинать год с Gradle.
Существует много причин не любить Gradle, но меня больше всего раздражает его "хрупкость". Есть много способов сделать одно и то же, но только один из них правильный, а остальные приведут к замедлению конфигурации проекта, несовместимости с configuration cache или проект вообще перестанет собираться.
Речь, конечно, про lazy API. Это прям штука про которую нужно знать сразу, как только начинаешь делать в Gradle что-то сложнее чем объявление зависимостей. Но не стоит терять бдительность после прочтения документации. Допустим, ты знаешь, что нужно использовать
А если хотим сконфигурировать все таски определённого типа? Можно написать так:
И это будет ошибка. Если в
Хорошо, а если хотим выключать таски по какому-то условию? Например, по флажку в
Ой-ой, опять ошибка! Нужно использовать
Так что в новом году желаю вам выбирать всегда правильные APIшки (и не только в Gradle). С Рождеством и Новым Годом :)
#gradle
С дядюшкой Бобом и без меня неплохо справляются, я бы мог разве что на его стороне выступить, но это не модно. А про Gradle мне есть что сказать. Если у вас в этот момент возникла мысль "прочитаю лучше после праздников", подумайте, хотите ли вы начинать год с Gradle.
Существует много причин не любить Gradle, но меня больше всего раздражает его "хрупкость". Есть много способов сделать одно и то же, но только один из них правильный, а остальные приведут к замедлению конфигурации проекта, несовместимости с configuration cache или проект вообще перестанет собираться.
Речь, конечно, про lazy API. Это прям штука про которую нужно знать сразу, как только начинаешь делать в Gradle что-то сложнее чем объявление зависимостей. Но не стоит терять бдительность после прочтения документации. Допустим, ты знаешь, что нужно использовать
tasks.named("javadoc")
, а tasks.getByName("javadoc")
в большинстве случаев не нужно, так как этот вызов создаёт запрошенный таск на месте вместо того чтобы возвращать ленивый провайдер. Но что если нужно сразу сконфигурировать этот таск? Вроде всё просто:tasks.named("javadoc") { enabled = false }
А если хотим сконфигурировать все таски определённого типа? Можно написать так:
tasks.withType<Javadoc> { enabled = false }
И это будет ошибка. Если в
withType
передать лямбду, то под капотом вызывается withType<T>().all(configure)
, а all
в моменте создаёт все таски в коллекции. Правильно будет делать так:tasks.withType<Javadoc>()
.configureEach { enabled = false }
Хорошо, а если хотим выключать таски по какому-то условию? Например, по флажку в
gradle.properties
:tasks.withType<Javadoc>().configureEach {
enabled = properties["tasks.javadoc"].toBoolean()
}
Ой-ой, опять ошибка! Нужно использовать
findProperty("...")
. Почему? Посмотрите документацию к getProperties... а, погодите, там ничего полезного не написано... тогда документацию к Project (скриншот снизу). Этот метод ищет "свойства" в более широком смысле — смотрит на поля convention'ов, Gradle-экстеншены, поля внутри Project
, все таски, extras, причём не только для текущего проекта, но и для всех родительских. И все это собирается в одну большую Map'у. Привести это может к довольно неожиданным проблемам.Так что в новом году желаю вам выбирать всегда правильные APIшки (и не только в Gradle). С Рождеством и Новым Годом :)
#gradle
Начал писать ворчливый комментарий к посту про SOLID, а потом подумал, что у меня ж есть канал, куда можно ворчать. Так что напишу сюда, хотя это немного не формат канала.
Во-первых, конечно, есть уже какое-то чувство усталости от бесконечных статей про SOLID, Clean Architecture и прочие новшества типа ЖЦ Activity.
А во-вторых... ИМХО, проблема всех статей с объяснением SOLID в том, что они пытаются каждый принцип объяснить как можно проще, на элементарных примерах. Чтобы человек посмотрел и сказал: "так SOLID это оказывается просто!". Но в итоге получается, что до применения SOLID было три строки кода, а после стало 10 классов и у читателя возникает только отторжение. Ну потому что дичь. До "рефакторинга" было коротко и понятно.
По сути основная цель SOLID – подстелить себе соломку на будущее, чтобы вносить изменения в существующий код было не "мучительно больно", а хотя бы просто "больно". А чтобы это понять нужно либо самому испытать что получается, когда принципы не соблюдаются, либо посмотреть на реальные примеры из практики, которые должны прям откликаться в сердечке. Такие примеры найти безумно сложно, даже в оригинальных статьях (S O L I D) примеры не всегда удачные. Поэтому, остаётся только пробовать приземлять SOLID на свой опыт, прочитав первоисточник с подробным объяснением принципов и проблем, которые эти принципы призваны решать.
Во-первых, конечно, есть уже какое-то чувство усталости от бесконечных статей про SOLID, Clean Architecture и прочие новшества типа ЖЦ Activity.
А во-вторых... ИМХО, проблема всех статей с объяснением SOLID в том, что они пытаются каждый принцип объяснить как можно проще, на элементарных примерах. Чтобы человек посмотрел и сказал: "так SOLID это оказывается просто!". Но в итоге получается, что до применения SOLID было три строки кода, а после стало 10 классов и у читателя возникает только отторжение. Ну потому что дичь. До "рефакторинга" было коротко и понятно.
По сути основная цель SOLID – подстелить себе соломку на будущее, чтобы вносить изменения в существующий код было не "мучительно больно", а хотя бы просто "больно". А чтобы это понять нужно либо самому испытать что получается, когда принципы не соблюдаются, либо посмотреть на реальные примеры из практики, которые должны прям откликаться в сердечке. Такие примеры найти безумно сложно, даже в оригинальных статьях (S O L I D) примеры не всегда удачные. Поэтому, остаётся только пробовать приземлять SOLID на свой опыт, прочитав первоисточник с подробным объяснением принципов и проблем, которые эти принципы призваны решать.
Ох, обычно я не удаляю посты, но в тут шутка вышла из под контроля, поэтому утренний пост дропнул.
Всем хорошего вечера :) Контент скоро будет
Всем хорошего вечера :) Контент скоро будет
Документация меня предупреждала, но я всё равно туда зачем-то полез...
Когда я только начал работать в команде Ktor, я поставил себе "внутреннюю цель" сделать так чтобы использовать Ktor на Android было максимально удобно. И вот в Ktor 3.2.0 благодаря моим правкам Android-проекты перестали собираться 🤡
Причина максимально глупая — пробелы в названиях полей. Возникает логичный вопрос: "Зачем?". А просто потому что когда-то я увидел подобный подход для компановки сообщений в Dokka и подумал "вау, как выразительно получается".
Перед тем как применить это в коде я подумал может ли это что-то сломать, и пришёл к выводу, что нет. Это ж константы, они при компиляции заинлайнятся и вообще использований не будет, что может пойти не так? То что D8 споткнётся о пробел я, конечно, не предусмотрел.
Так что вы знаете кого винить, что не получается обновиться на новый Ktor. А я пойду думать как на CI гонять проверки, что проекты с Ktor собираются с D8, R8 и ProGuard.
P.S. Workaround нашёлся, но достаточно страшный. Через AGP Transformation API вырезать проблемные поля 🙈
Причина максимально глупая — пробелы в названиях полей. Возникает логичный вопрос: "Зачем?". А просто потому что когда-то я увидел подобный подход для компановки сообщений в Dokka и подумал "вау, как выразительно получается".
Перед тем как применить это в коде я подумал может ли это что-то сломать, и пришёл к выводу, что нет. Это ж константы, они при компиляции заинлайнятся и вообще использований не будет, что может пойти не так? То что D8 споткнётся о пробел я, конечно, не предусмотрел.
Так что вы знаете кого винить, что не получается обновиться на новый Ktor. А я пойду думать как на CI гонять проверки, что проекты с Ktor собираются с D8, R8 и ProGuard.
P.S. Workaround нашёлся, но достаточно страшный. Через AGP Transformation API вырезать проблемные поля 🙈