При разработке мобильных приложений часто возникает необходимость иметь возможность включать/выключать или параметризировать функциональность по разным причинам как при изначальной сборке приложения, так и в уже собранном или даже выпущенном приложении. В этой статье мы рассмотрим разные подходы к конфигурированию функциональности мобильных приложений и их преимущества и недостатки.
Конфигурирование функциональности может быть полезно для разных целей, например:
Добавления отладочной панели или ключей для тестирования приложения
Управления новой функциональностью, которая еще не протестирована или не готова к релизу
Запуска AB-тестов для проверки продуктовых гипотез и измерения эффективности изменений
Адаптации приложения к разным регионам, языкам или платформам
Реагирования на изменения внешних условий, например рекламных кампаний или доступности сервисов
В зависимости от того, на каком этапе жизненного цикла приложения мы хотим конфигурировать его функциональность, мы можем использовать разные способы
Конфигурация на уровне сборки
Самый простой вариант конфигурации — это использование параметров, которые задаются при сборке приложения. Такие параметры могут, например, отвечать за добавление в код приложения кода отладочной панели, или для задания отладочных ключей. Тогда для сборки отладочной версии приложения может использоваться один конфигурационный файл, а для релизной - другой.
Пример конфигурационного файла (Android приложение):
// gradle.properties
isDebugPanelEnabled=true
// build.gradle
dependencies {
...
if (getProperty("isDebugPanelEnabled")) {
implementation ':libs:debug'
}
...
}
Главное преимущество такой конфигурации — это простота реализации, но, когда приложение уже собрано, изменить значения параметров уже не получится. Такая конфигурация не позволяет управлять функциональностью для конкретных пользователей или групп пользователей.
Локальная конфигурация
Часто бывает необходимо иметь версию приложения, в которой можно включать/выключать и настраивать существующую функциональность на одной сборке. Например, такая необходимость часто возникает при тестировании приложения, когда в одной сборке есть как отлаженная функциональность, так и новая, непротестированная. Такую функциональность хочется “убрать под флаг”, чтобы в случае обнаружения в новой функциональности дефектов не блокировать релизный процесс мобильного приложения.
Для реализации такой возможности необходимо разработать отдельную отладочную панель - экран, на котором можно управлять состоянием флагов. Хороший пример - отладочная панель в ОС Android. Она позволяет, например, настраивать плотность пикселей на устройстве или включить отображение границ UI-компонентов.
![Отладочная панель в ОС Android Отладочная панель в ОС Android](https://habrastorage.org/getpro/habr/upload_files/36e/747/070/36e7470706e77a489591801bf27a90b4.png)
Преимущество локальной конфигурации — это возможность изменять значения флагов в любой момент на конкретном устройстве. Недостаток — это необходимость разработки и поддержки отладочной панели, а также отсутствие возможности управлять функциональностью удаленно.
Удалённая конфигурация
В некоторых случаях необходимо управлять параметрами удаленно с сервера. В этом случае на старте приложение запрашивает конфигурацию у специального сервера и использует ее для включения/выключения функциональности и ее настройки. Такая необходимость может появиться если, например, необходимо выложить приложение с функциональностью в выключенном состоянии, а затем включить ее в определенный момент времени, например к началу рекламной кампании.
Дополнительная механика, которую можно поддержать для удаленных конфигураций — это раздача конфигураций “на процент”. В этом случае для части пользователей возвращаются одни значения, а остальным - другие. Это можно использовать, например, для постепенного включения новой функциональности и соответствующего увеличения нагрузки на новые методы API, чтобы убедиться, что сервер справится с нагрузкой.
Дополнительно для удаленных флагов можно предусмотреть версионирование, так как при обнаружении дефектов в приложении и их последующем исправлении при переключении флага функциональность с дефектом станет доступна пользователям, если они не обновили приложение.
Этот вариант очень удобен для запуска функциональности в привязке ко времени, а также для поэтапной раскатки функциональности на часть пользователей. Тем не менее здесь необходимо реализовывать клиент-серверное взаимодействие и административную панель для управления состояниями флагов. В самых простых случаях для реализации удаленной конфигурации можно использовать готовые решения, например, Firebase Remote Config.
Конфигурация AB-теста
Однако, самым распространенным для сложных продуктов сценарием, подразумевающим включение/выключение функциональности и управление ее параметрами, является запуск AB-экспериментов. С точки зрения приложения этот вариант очень похож на вариант с удаленной конфигурацией, но логика на серверной стороне отличается. В рамках AB-теста сегмент пользователей делится на группы: контрольную, которая получает исходную версию продукта, и тестовую, которая получает версию продукта с новой функциональностью. Каждая группа пользователей получает свою версию конфигурации и соответственно, по-разному сконфигурированную функциональность в приложении. По каждой группе пользователей измеряются продуктовые метрики, и если версия приложения с тестовой конфигурацией признается лучшей, то такой эксперимент принимают и версия приложения с новой функциональностью становится исходной версией для новых экспериментов. Вопросы выбора сегмента пользователей для AB-эксперимента и их дальнейшее разбиение на группы эксперимента вынесем за рамки этой статьи.
Реализация административного раздела для создания AB-экспериментов, настройка их параметров, а также настройка инструментов для анализа их результатов - отдельная и сложная задача. Тем не менее для самых простых случаев также можно использовать готовые решения, например, Firebase.
Всё вместе
Очень часто все эти способы управлять функциональностью приложения реализуют вместе, и возникает вопрос, а какой источник для значения параметра выбрать, если значения из разных источников отличаются.
Локальная конфигурация — это самый удобный способ изменить значение параметров на конкретном устройстве. Поэтому этот источник можно считать самым “сильным” и в первую очередь использовать значение оттуда. Если в локальной конфигурации значение параметра не переопределено, то необходимо использовать значение, полученное с сервера.
Удаленная конфигурация и конфигурация AB-теста объединяет то, что обе они запрашиваются с сервера и с точки зрения мобильного приложения часто неразличимы. Эти варианты редко используются вместе, но такие сценарии возможны. Например, когда новую функциональность необходимо запустить через AB-эксперимент, но при этом иметь возможность отключать ее совсем без остановки теста, если, например, используемый для работы функциональности сервис временно отказал. В таких случаях предпочтение следует отдавать значению удаленной конфигурации.
Параметры из конфигурации на уровне сборки очень часто используются в качестве значений по умолчанию, поэтому используются, если ни в одном другом источнике они не переопределены.
![Выбор источника значения параметра Выбор источника значения параметра](https://habrastorage.org/getpro/habr/upload_files/a92/5a7/609/a925a7609fd009956bd5d51aff524a1e.png)
Выводы
В статье были рассмотрены подходы к конфигурированию функциональности мобильных приложений как на этапе сборки, так и когда приложение уже собрано или даже выпущено. Для реализации этих подходов есть готовые решения, однако в больших командах часто используются собственные решения, которые учитывают специфику конкретных команд и продуктов. При использовании таких конфигураций можно упростить процесс разработки и тестирования мобильного приложения, а также обеспечить возможность проверки продуктовых гипотез через AB-тесты.