Привет. Меня зовут Кирилл Розов и вы если вы интересуетесь разработкой под Android, то скорее всего слышали о Telegram канале "Android Broadcast", с ежедневными новостями для Android разработчиков, и одноимённом YouTube канале. Этот пост является текстовой расшифровкой видео на канале
Современные мобильные приложения уже вполне серьезные Enterprise проекты, которые разрабатываются десятками, а то и сотнями разработчиков, содержат в себе тысячи строк кода и постоянно меняются и развиваются. Уследить за такой огромной кодовой базой помогает процесс автоматизации проверок кода и работы приложения. Сегодня расскажу о том, какие инструменты вы можете использовать, чтобы улучшить стабильность вашего проекта и не допускать ошибок, а также сэкономить время коллегам во время pull request.
Вы разрабатываете проект в маленькой команде, а то и вовсе один? Тогда эта статья вам еще важнее, так как вы скорее всего не настраивали у себя никакие проверки, а я расскажу почему это нужно сделать.
Типы проверки кода
Проверка кода делится на 2 типа:
статический анализ кода (без запуска приложения)
анализ работы кода во время работы приложения
В Android разработке используются компилируемые языки со статической типизацией: Java и Kotlin. Это важные требования к языкам, которые позволяют выполнять анализ код без необходимости его запуска и может это делать прямо на лету во время его написания. Такой тип анализа называется статическим. Это позволяет легко запускать такие утилиты во на любом CI и автоматизировать проверку простых ошибок, например что вы не закрыли поток после чтения/записи. Минус таких проверок, что если ваш код отходит от шаблона заложенного в них, то они уже не сработают или будут работать некорректно. Также такие анализаторы не могу понять сложные сценарии выполнения кода и их эффект.
Более серьезные проверки вашего кода можно сделать с помощью его автоматического анализа во время работы приложения (динамические). Например, так можно отследить утечку памяти или проблемы, которые происходят из-за подключенных библиотек. Самая известная утилита из таких - LeakCanary
. Главный минус таких инструментов - необходимость запуска на реальных устройствах, что усложняет автоматическую проверку на CI, так как вам надо иметь подключенные устройства к серверу или платить за использование фермы.
Инструменты для анализа кода
IDEA Code Inspections
Первый инструмент с которым неявно сталкивается любой разработчик - IDE. Современные IDE - это не только подсветка синтаксиса и автодополнение, но и анализ кода, поиск ошибок в нём и прочие подсказки. IDEA имеет множество проверок для Java и Kotlin, которые работают из коробки, а в каждой новой версии происходят улучшения работы старых проверок и список пополняется новыми.
Минус проверок из IDEA - чтобы их запустить на CI вам нужна IDEA, но с появлением проекта Qodana теперь стало проще. Вы можете использовать Docker образ, интегрировать плагин для TeamCIty или настроить GitHub приложение. На момент выхода этой статье Qodana находится в разработке и про её платность ничего неизвестно.
Проверка стиля кода
Как часто вас бесило, что новый разработчик не соблюдает стиль кода приложения? Если у вас такого нет, то скорее всего вы уже настроили у себя утилиты, которые проверяют соответствие кода вашему стилю.
Checkstyle - анализ стиля Java кода
Checkstyle - это очень мощное и гибкое решение, которое используется для проверки соответствия стиля кода стандарту, принятому в команде. Только Java кода, что уже не очень актуально для современное Android разработки, которая перешла на Kotlin, но очень актуально для Backend разработки, где Java доминирует. Checkstyle позволяет производить очень гибкую настройку параметров и описать любые требования к оформлению Java кода.
ktlint
Для проверки стиля Kotlin кода есть утилита ktlint от Pinterest. Утилита не такая гибкая по своим паратмерам как Checkstyle и позволяет задать только некоторые параметры. Все правила заданы на соотвествие Kotlin Coding Convention и Android Kotlin Style Guide c учётом настроек из .editorconfig
. Также утилита позволяет форматировать ваш Kotlin код. Ktlint развивается неспешно и за несколько лет существования всё еще не вышла в стабильный релиз, но работает без проблем и обновляются для поддержки новой версии языка. К сожалению, иногда она обновляется с задержками, что не даёт полноценно обновить проект на новую версию Kotlin.
EditorConfig
Еще один важный инструмент для того чтобы пошарить общий стиль кода между разработчиками - это файл .editorconfig. Это специальный файл в котором содержится параметры стиля кода и настройки плагинов редактора. Вы описываете общие параметров для всех файлов, а также можете задать особые значения для отдельных файлов так и группы файлов на основе шаблона. EditorConfig поддерживается IDEA и AndroidStudio и есть специальный плагин.
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8
# 4 space indentation
[*.py]
indent_style = space
indent_size = 4
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
PMD (ранее Findbugs)
PMD - это расширяемый статический анализатор кода с поддержкой множества языков, а также может находить «Copy-paste». PMD нас интересует в первую очередь из-за поддержка Java т.к. поддержки Kotlin нет. PMD активно развивается и набирает обороты, но в Android мире становится всё менее популярен из-за массового перехода на Kotlin.
Error Prone от Google
Google Error Prone - eщё один статический анализатор Java кода, который будет вызывать ошибки во время компиляции при нарушении правил. Вы также можете написать свои собственные правила и подключать их отдельно, либо попробовать законтрибьютить в основной репозиторий. Этим инструментов я пользовался несколько раз. А вы использовали его у себя? Пишите в комментариях!
Android Lint - комплексный анализ Android проектов
Android Lint - это официальное решение от команды Android для анализа ваших Android проектов. Вы можете проверять любой файл, который есть в проект: код, ресурсы, AndroidManifest и др. Преимуществом инструмента является, что анализ может выполняться не только в одном файле, но и между файлами в рамках проекта. Например, вы можете считать конфигурацию из AndroidManifest и его основе понять нужно ли выдавать предупреждения или нет.
Android Lint позволяет создавать свои правила и легко паковать из вместе с вашими библиотеками как часть AAR архива, а Android тулинг автоматом подключит их в проект.
Всё звучит очень прекрасно, но есть ряд недостатков. Самый главный недостаток - скорость работы. Запуск проверок на всём проекте можете занимать десятки минут, поэтому запускать в рамках пулл реквестов проблематично. Хотя может Apple Silicon настолько могучт, что и тут вытянет всё )
Также API для написания правил все ещё не финально и постоянно меняется, хотя не так давно появилась полноценная документация и описания всей применяемой терминологии и больше примеров.
rxlint - набор проверок для Android, которые проверяют Rxjava
Если вы активно используете RxJava у себя в проекте, тогда в дополнение к Android Lint, рекомендую вам подключить этот набор проверок, чтобы избегать ошибок.
detekt - анализ Kotlin кода
Если вы хотите решение статического анализа кода для Kotlin - тогда Detekt это ваш выбор. Утилита постоянно развивается, улучшаются существующие проверки и добавляются новые. Вы можете включить/выключить любую проверка, а также настроить ее под себя. Помимо прочего можно писать свои правила и распространять их. Например, таким образом ktlint полностью интегрирован через detekt-format. Detekt имеет множество интеграций с современным популярными инструментами. К его минусам можно отнести, что не все правила работают корректно, а некоторые и вовсе не срабатывают, но инструментов для анализа Kotlin кода кроме проверок IDEA и Android Lint нет, поэтому Detekt стал стандартом. Для интеграции Detekt с Android Studio/IDEA рекомендую вам установить одноимённый плагин - detekt.
SonarQube
Я рассказал вам про множество решений и управлять всеми ими и следить за качеством может быть очень непросто, поэтому нужен какой-то качественный аггрегатор. Таким инструментом служит SonarQube, который помимо своих собственных правил, способен понимать отчёты других инструментов и добавлять их в единый отчёт по проекту. Собственные правила написаны у них замечательно и во время разработки Android приложений на Java я многому научился, благодаря качественному описанию причин проблем и как их исправить.
Sonarqube имеет бесплатную версию, которой хватит Android разработчикам, но её надо разворачивать на собственном сервере либо придется платить за версию в облаке. Если у вас Open Source проект, то вы сможете вполне воспользоваться облачной версией без ограничений - SonarCloud. Пример анализа популряных Open Source проектов можно найти здесь.
К минусам SonarQube я могу отнести малое количество правил для Kotlin (на момент написания статьи), а также отсутствие официальной интеграции с Android Lint. Стороннее расширение не добавляет всех правил, что расстраивает и делает отчёт менее полезным.
Анализ во время работы приложения
Переходим к утилитам, которые анализируют ваш код во время работы приложения. Я настоятельно рекомендую включать их только во время разработки и чтобы их код не попадал в production сборки. Самый банальный способ - проверять дебажная сейчас сборка или нет и на основе этого инициализировать библиотеку или нет. Продвинутый способ исключения такого кода - подключать библиотеку только в тестовые сборки, что потребует от вас правильно организации кода и расскладывать код по разным папкам с исходниками.
Android Strict Mode
StrictMode - это стандартный инструмент в Android SDK, который появился еще в Android 2.3 и позволяет включать различные правило. Если правило нарушается, тогда произойдёт реакция, которой вы можете управлять. Реакцией может быть сообщение в Logcat, показ диалога или креш приложения. В более поздних версиях можно задать callback и трекать проблему в Firebase Crashlytics или аналогичные сервисы для сборка крешей.
Утилита обладает огромным количеством правил, которые пополняются в каждой версии Android. Их проблема заключается в том что они фрагментированы и нет Compat API. Это досадное недоразумение я исправил своей библиотекой, которое помимо этого еще добавляет и Kotlin DSL для конфигурирования - StrictModeCompat
class SampleApp : Application() {
fun onCreate() {
if (DEVELOPER_MODE) { // Не включать в боевом приложении!!!
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
)
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build()
)
}
super.onCreate()
}
}
LeakCanary
Если вы еще не слышали про LeakCanary, значит вы не задумывались про то как отследить утечки памяти в вашем Android приложение. Это замечательная разработка интегрируется в ваше приложение, показывает утекающие объекты и даёт создавать дампы, которыми легко могут с вами поделиться QA. Сделано всё супер удобно и приятно. Рекомендую для интеграции. Также его можно интегрировать с вашим инструментов для отслеживания крешей.
ANR-WatchDog
Никто не хочет чтобы приложение тормозило, в особенности чтобы пользователь увидел ANR диалог. ANR-WatchDog следит за тем чтобы у вас не происходили ANR и позволяет вам их отследить до ухода в production. При нахождении таких проблем в Logcat будет сыпаться специальная ошибка с подробностями. Также мы можете ее отловить и отсылать в Crashlytics или другие сервисы
Заключение
В комментариях я предлагаю вам рассказать о ваших способах автоматизации отслеживания проблем и поддерживания уровня качества кода в ваших проектах и инструменты, которые используете для этого.