- Строгий режим
- Автоматизация повышения качества кода в Android
- Типы проверки кода
- Инструменты для анализа кода
- IDEA Code Inspections
- Проверка стиля кода
- Checkstyle — анализ стиля Java кода
- ktlint
- EditorConfig
- PMD (ранее Findbugs)
- Error Prone от Google
- Android Lint — комплексный анализ Android проектов
- rxlint — набор проверок для Android, которые проверяют Rxjava
- detekt — анализ Kotlin кода
- SonarQube
- Анализ во время работы приложения
- Android Strict Mode
- LeakCanary
- ANR-WatchDog
- Заключение
Строгий режим
StrictMode — инструмент для обнаружения потенциальных проблем в приложении. Также как и Fragment , StrictMode не рендерит видимого UI. Строгий режим активирует дополнительные проверки и предупреждения для своих потомков.
Проверки строгого режима работают только в режиме разработки; они не оказывают никакого эффекта в продакшен-сборке.
Строгий режим может быть включён для любой части приложения. Например:
В примере выше проверки строгого режима не будут выполняться для компонентов Header и Footer . Однако будут выполнены для ComponentOne и ComponentTwo , а также для всех их потомков.
На данный момент StrictMode помогает в:
Дополнительные проверки будут включены в будущих релизах React.
Обнаружение небезопасных методов жизненного цикла
В этой статье рассматриваются причины, почему некоторые методы жизненного цикла небезопасно использовать в асинхронных React-приложениях. Если в приложении подключены сторонние библиотеки, то отследить использование таких методов довольно тяжело. К счастью, тут может помочь строгий режим!
Когда строгий режим включён, React составляет список всех классовых компонентов, которые используют небезопасные методы жизненного цикла, и отображает информацию о них таким образом:
Если избавиться от проблем, выявленных в строгом режиме, уже сегодня, то это позволит получить все преимущества конкурентного рендеринга в будущих релизах React.
Предупреждение об использовании устаревшего API строковых реф
Ранее React предоставлял два способа управления рефами: устаревшие строковые рефы и колбэк API. Хотя строковые рефы и были более удобным способом, они имели несколько недостатков. Поэтому мы рекомендовали использовать колбэки вместо них.
В React 16.3 добавлен третий способ, который предлагает удобство строковых рефов и лишён каких-либо недостатков:
Поскольку объекты-рефы стали заменой строковых реф, строгий режим теперь предупреждает об использовании строковых реф.
Колбэк-рефы по-прежнему поддерживаются вместе с новым API-методом createRef .
Вам не обязательно заменять колбэк-рефы в ваших компонентах. Их использование более гибкое, поэтому они считаются продвинутой возможностью.
Предупреждение об использовании устаревшего метода findDOMNode
Ранее React использовал findDOMNode для поиска DOM-узла в дереве по указанному экземпляру класса. В большинстве случаев этот метод не используется, поскольку можно привязать реф непосредственно к DOM-узлу.
findDOMNode может использоваться для классовых компонентов, однако это нарушает уровни абстракции, позволяя родительскому компоненту требовать, чтобы происходил рендер определённых дочерних элементов. Это приводит к проблемам при рефакторинге, когда не удаётся изменить детали реализации компонента, так как родитель может использовать DOM-узел этого компонента. findDOMNode возвращает только первый дочерний элемент, но с использованием фрагментов компонент может рендерить несколько DOM-узлов. findDOMNode выполняет поиск только один раз. Затем метод возвращает ранее полученный результат при вызове. Если дочерний компонент рендерит другой узел, то это изменение никак не отследить. Поэтому findDOMNode работает, только когда компоненты возвращают единственный и неизменяемый DOM-узел.
Вместо этого, можно передать реф в компонент и передать его далее в DOM используя перенаправление рефов.
Также можно добавить компоненту DOM-узел как обёртку и прикрепить реф непосредственно к этой обёртке.
CSS-выражение display: contents может применяться для исключения узла из макета (layout).
Обнаружение неожиданных побочных эффектов
React работает в два этапа:
- Этап рендеринга (render phase) определяет, какие изменения необходимо произвести, например, в DOM. В течение этого этапа React вызывает render , а затем сравнивает полученный результат с результатом предыдущего рендера.
- Этап фиксации (commit phase) — в нём React применяет любые изменения. В случае React DOM — это этап, когда React вставляет, обновляет и удаляет DOM-узлы. В течение этого этапа React вызывает методы жизненного цикла componentDidMount и componentDidUpdate .
Этап фиксации обычно не занимает много времени, что нельзя сказать про этап рендеринга. По этой причине, готовящийся конкурентный режим (который по умолчанию ещё не включён) делит работу на части, периодически останавливает и возобновляет работу, чтобы избежать блокировки браузера. Это означает, что на этапе рендеринга React может вызвать методы жизненного цикла более чем один раз перед фиксацией, либо вызвать их без фиксации (из-за возникновения ошибки или прерывания с большим приоритетом).
Этап рендеринга включает в себя следующие методы жизненного цикла:
- constructor
- componentWillMount (или UNSAFE_componentWillMount )
- componentWillReceiveProps (или UNSAFE_componentWillReceiveProps )
- componentWillUpdate (или UNSAFE_componentWillUpdate )
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- Функции обновления setState (первый аргумент)
Поскольку вышеупомянутые методы могут быть вызваны более одного раза, важно, чтобы они не приводили к каким-либо побочным эффектам. Игнорирование этого правила может привести к множеству проблем, включая утечки памяти и недопустимое состояние приложения. К сожалению, такие проблемы тяжело обнаружить из-за их недетерминированности.
Строгий режим не способен автоматически обнаруживать побочные эффекты, но помогает их отследить, сделав более детерминированными. Такое поведение достигается путём двойного вызова следующих методов:
- Методы constructor , render , и shouldComponentUpdate классового компонента
- Статический метод классового компонента getDerivedStateFromProps
- Тело функционального компонента
- Функции обновления (первый аргумент setState )
- Функции, переданные в useState , useMemo , или useReducer
Это применимо только в режиме разработки. Методы жизненного цикла не вызываются дважды в продакшен-режиме.
Рассмотрим следующий пример:
На первый взгляд данный пример не кажется проблемным. Но если метод SharedApplicationState.recordEvent не является идемпотентным, тогда создание этого компонента несколько раз может привести к недопустимому состоянию приложения. Такие труднонаходимые ошибки могут никак не проявить себя во время разработки или быть настолько редкими, что останутся незамеченными.
Двойной вызов таких методов, как конструктор компонента, позволяет строгому режиму легко обнаружить подобные проблемы.
Начиная с 17 версии, React автоматически модифицирует методы для работы с консолью (например, console.log() ), чтобы предотвратить запись в консоль при втором вызове функций жизненного цикла. Однако в некоторых ситуациях это может привести к нежелательному поведению, в таких случаях можно воспользоваться обходным решением.
Обнаружение устаревшего API контекста
Использование устаревшего API контекста очень часто приводило к ошибкам и поэтому он будет удалён в будущей мажорной версии. Пока что этот API доступен во всех релизах 16.x, но в строгом режиме будет выведено следующее предупреждение:
Ознакомьтесь с документацией нового API контекста, чтобы упростить переход на новую версию.
Источник
Автоматизация повышения качества кода в Android
Привет. Меня зовут Кирилл Розов и вы если вы интересуетесь разработкой под 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 находится в разработке и про её платность ничего неизвестно.
Проверки в Android Studio 4.2
Проверка стиля кода
Как часто вас бесило, что новый разработчик не соблюдает стиль кода приложения? Если у вас такого нет, то скорее всего вы уже настроили у себя утилиты, которые проверяют соответствие кода вашему стилю.
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 и есть специальный плагин.
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
LeakCanary
Если вы еще не слышали про LeakCanary, значит вы не задумывались про то как отследить утечки памяти в вашем Android приложение. Это замечательная разработка интегрируется в ваше приложение, показывает утекающие объекты и даёт создавать дампы, которыми легко могут с вами поделиться QA. Сделано всё супер удобно и приятно. Рекомендую для интеграции. Также его можно интегрировать с вашим инструментов для отслеживания крешей.
ANR-WatchDog
Никто не хочет чтобы приложение тормозило, в особенности чтобы пользователь увидел ANR диалог. ANR-WatchDog следит за тем чтобы у вас не происходили ANR и позволяет вам их отследить до ухода в production. При нахождении таких проблем в Logcat будет сыпаться специальная ошибка с подробностями. Также мы можете ее отловить и отсылать в Crashlytics или другие сервисы
Заключение
В комментариях я предлагаю вам рассказать о ваших способах автоматизации отслеживания проблем и поддерживания уровня качества кода в ваших проектах и инструменты, которые используете для этого.
Источник