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

Как мы упоминали в последней статье, наше приложение Doctors App стало MVP и очень быстро росло.

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

Чтобы исправить эту ситуацию, нашим первым шагом было выявление точек улучшения. У нас был технический долг, хорошо. Но вопрос был такой:

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

После исчерпывающего анализа мы обнаружили следующие улучшения:

  • ИСПОЛЬЗОВАНИЕ REACT
  • ГЛОБАЛЬНОЕ ГОСУДАРСТВЕННОЕ УПРАВЛЕНИЕ
  • ОТСУТСТВИЕ ТЕСТА
  • CI & RELEASE PROCESS

Ниже мы собираемся описать проблемы каждого блока, решение, которое мы применили, и причину этого решения.

ИСПОЛЬЗОВАНИЕ REACT

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

Наш код был основан в основном на больших компонентах на основе классов на каждом экране. При таком подходе мы выявили следующие проблемы:

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

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

Плохая возможность повторного использования компонентов. Прямое следствие наличия огромных компонентов.

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

Совместное использование логики между компонентами. Мы использовали нерекомендованные способы повторного использования логики компонентов, например наследование в одних местах, и использовали HOC в других, где были лучшие варианты.

Встроенная верстка

После анализа точек улучшения, описанных выше, были указаны наши действия и преимущества / улучшения, которые мы получили после их применения:

  • Обновление версий React и React Native. Первым шагом было обновление фреймворка до последней версии, чтобы можно было использовать все новейшие функции.
  • Разделите большие компоненты на более мелкие. Благодаря этому действию мы улучшили управление рендерингом, получили больше кода с возможностью повторного использования, а компоненты стали проще читать, понимать и тестировать.
  • Используйте крючки и специальные крючки. С помощью хуков мы могли извлечь некоторую бизнес-логику, которая у нас есть в разных компонентах, и поделиться ими. Кроме того, имея изолированную часть с этой логикой, добавление тестирования становится более осуществимым.
  • Стилизованные компоненты. Мы использовали стилизованные компоненты, чтобы избавиться от встроенных компонентов, при этом у нас были еще более мелкие и красивые компоненты.

Отлично! На шаг ближе!

ГЛОБАЛЬНОЕ ГОСУДАРСТВЕННОЕ УПРАВЛЕНИЕ

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

Мы рассмотрели следующие альтернативы, чтобы улучшить этот момент:

Рефакторинг текущего решения с помощью Redux + Saga. Мы знаем, что есть много успешных приложений, использующих этот подход, поэтому одним из вариантов был рефакторинг текущего решения с упором на:

  • Уменьшите побочные эффекты, сделайте более изолированные саги.
  • Перепишите логику на более мелкие саги, дав им значимые имена.
  • Добавьте во все эти саги модульное тестирование.

Используйте React Context API. Начиная с версии Context API, React предоставляет собственное решение для совместного использования глобального состояния.

Такие библиотеки, как Redux или Mobx, в конечном итоге могут быть заменены этим подходом, особенно в небольших приложениях с небольшими объемами данных.

Используйте Apollo. Apollo - это не только фреймворк для управления коммуникациями на основе GraphQL, Apollo - это инструмент, с помощью которого вы также можете:

  • Работа с Rest API.
  • Используйте множество утилит, таких как контроль кеша, опрос или обновление.
  • Используйте кеш Apollo для сохранения данных во всем приложении (так же, как мы можем делать с Redux / Context API), и мы можем сохранить эту информацию.

Проверив все варианты и подумав о будущем мобильном шлюзе в Graph QL (возможно, это тема для другой статьи), мы решили использовать Apollo.

ОТСУТСТВИЕ ТЕСТА

Прохладный! Итак, после последних блоков у нас есть красивое, современное и масштабируемое приложение.

Однако, учитывая, что мы делали приложение React Native, мы выпускаем его как для iOS / Android, так и для сотен устройств, добавление тестов было обязательным:

Модульный и интеграционный тест

После рефакторинга, описанного выше, было намного проще добавлять модульные тесты в наш проект (в настоящее время у нас их более 700!). Для добавления хороших модульных и интеграционных тестов мы использовали следующие библиотеки:

Сквозной тест

Мы делаем мобильное приложение на React Native, и вот некоторые из связанных фактов:

  • Мы поставляем наше приложение для двух разных операционных систем (iOS и Android).
  • Мы поставляем приложение на сотни устройств.
  • Релизы на мобильных устройствах требуют своего времени (создавать сборки, отправлять в магазины, обзоры).
  • Развернутый код - это фиксированный код, который может оставаться до тех пор, пока пользователь не обновит приложение.

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

Для этой цели мы выбрали Appium и BrowserStack, просмотрите эту статью, чтобы углубиться в эту тему.

CI & RELEASE PROCESS

Последними улучшениями стали CI и процесс выпуска. В связи с этой темой мы добавили некоторые улучшения на разных уровнях.

Уровень развития. Мы добавили Действия Github, которые запускают тесты и передают линтер в качестве необходимого шага для объединения любого PR. Мы также заблокировали ветки master и development и потребовали получить хотя бы одно разрешение на их объединение.

Уровень выпуска. Мы автоматизировали процесс выпуска с помощью Azure Pipes и создания различных каналов:

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

Заключительные мысли

После нашего путешествия, описанного в этой статье, мы наконец получили надежное приложение с:

  • Современный React с небольшими и изолированными частями (функциональные компоненты и хуки).
  • Хороший инструмент для создания макетов (Стилизованные компоненты).
  • Apollo, мощный инструмент для обмена данными, управления коммуникациями и открытая дверь для GraphQL.
  • Модульное и Тестирование
  • Процесс выпуска.

Итак, мы заслужили потрясающий торт!

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

Продолжить серию

Часть 1 - Мотивация n

Часть 2. Рефакторинг

Часть 3 - Общение

Если вам понравился этот пост, нажмите кнопку хлопка ниже :) Вы также можете подписаться на нас в Facebook, Twitter и LinkedIn.