Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Make Experiments Great Again, или Как iOS Браузер А/Б тестирование улучшал

Make Experiments Great Again, или Как iOS Браузер А/Б тестирование улучшал

CocoaHeads

October 04, 2019
Tweet

More Decks by CocoaHeads

Other Decks in Programming

Transcript

  1. Make Experiments Great Again, или Как iOS Браузер А/Б тестирование

    улучшал Андрей Сикерин, iOS разработчик, CocoaHeads Russia, 4 октября 2019
  2. Исходная система экспериментов 3 1. Основана на Chromium и была

    поддержана в iOS не полностью. 2. Умеет раскатывать фичи на разные группы пользователей. 3. Имеет систему фильтров (версия приложения, локаль устройства). 4. Файл состоит из описаний конфигураций экспериментов и закодирован в protobuf. 5. Каждая конфигурация состоит из групп экспериментов. Фича в коде привязывается к активной группе эксперимента.
  3. Принципы работы системы экспериментов 4 1. Файл с описаниями всех

    конфигураций экспериментов выкладывается на сервер. 2. При запуске он скачивается и сохраняется локально. 3. При следующем старте, мы декодируем файл и для каждого эксперимента находим активную конфигурацию. 4. Выбираем активную группу эксперимента внутри конфигурации. Система экспериментов ничего не хранит сама, все считается
  4. Конфигурация эксперимента Переводчик, public beta, все пользователи 5 study {

    name: "translator" experiment { name: "enabled" probability_weight: 1000 } filter { channel: BETA ya_min_version: "19.3.4.43" } }
  5. Механика экспериментов (деление пользователей на группы) 6 Группы пользователей X

    дата релиза Старые (install date <= X - 21) Без эксперимента Новые install date >= X+3
  6. Конфигурации эксперимента Переводчик app store, новые пользователи 7 study {

    name: “translator” experiment { name: "enabled_new" probability_weight: 500 } experiment { name: "control_new" probability_weight: 500 } filter { channel: STABLE ya_min_version: “19.4.1.*" # 18 Apr 2019 min_install_date: 1555545600 } }
  7. 8 Виды групп экспериментов Контрольная группа |X| Дефолтная группа |1

    - 2Х| Фичевые группы |Х| Конфигурации эксперимента Переводчик app store, новые пользователи
  8. Конфигурация эксперимента Переводчик app store, старые пользователи 9 study {

    name: "translator" experiment { name: "enabled_old" probability_weight: 100 } experiment { name: "control_old" probability_weight: 100 } experiment { name: "default_old" probability_weight: 800 } filter { channel: STABLE platform: PLATFORM_IOS ya_min_version: “19.4.1.*" # 28 Mar 2019 max_install_date: 1553731200 } }
  9. Выбор группы эксперимента - работа из кода 10 enum TranslatorState

    { case enabled case disabled } func GetState() -> TranslatorState { let trialGroup = FieldTrialList.FindFullName("translator") if (trialGroup == "enabled_old" || trialGroup == "enabled_new" || trialGroup == "enabled") { return .enabled; } return .disabled; }
  10. Недостатки старой системы экспериментов 11 1. Нельзя добавить новые группы

    без исправления кода. 2. Нельзя раскатить часть фичи или разбить фичу на части. 3. Нельзя конфигурировать фичу и сравнивать конфигурации. 4. Аналитики и разработчики вынуждены согласовывать названия групп заранее. Хватит это терпеть - Make Experiments Great Again

  11. Feature & Param 13 experiment { name: "enabled" feature_association {

    enable_feature: “TranslatorFeature" enable_feature: "TranslateServiceAPITimeout" } param { name: "timeout" value: "5000" } probability_weight: 1000 }
  12. Feature & Param: работа из кода 14 struct Feature {

    let name: String let state: FeatureState } struct FeatureParam<T> { let name: String let featureName: String let value: T } let translatorFeature = Feature( name: "TranslatorFeature" state: .enabled) let APITimeoutFeature = Feature( name: "TranslateServiceAPITimeout" state: .disabled) let apiTimeoutParam = FeatureParam<Int>( name: serviceAPITimeoutFeature.name, featureName: "timeout", value: 300) func GetRequestTimeout() -> Int { return apiTimeoutParam(); } func GetState() -> TranslatorState { return FeatureList.IsEnabled( translatorFeature) ? .enabled : .disabled }
  13. Feature & Param: проблема 15 1. Нельзя задать принудительно Feature&FeatureParam.

    2. Нельзя посмотреть значения Feature&FeatureParam. 3. Нужно выкатить файл с конфигурацими экспериментов в Production для тестирования. Тестировщику тяжело тестировать еще не вышедшую фичу

  14. Feature & Param: решение 16 1. Начали использовать новый сервис

    для выкладки конфига, сделали настройку для подмены источника конфигурации экспериментов. 2. Поддержали часть ?show-variations-cmd на странице browser://version. 3. Сделали систему cheat-урлов, дополняющие систему экспериментов. 4. Начали разрабатывать диагностический экран.
  15. Новый сервис для выкладки конфига 17 1. Скачаваем и дополнить

    study- файл фейковым экспериментом указав в ней требуемые enabled/ disabled feature и params 2. Выложить данный конфиг на новые сервис. Получим ссылку на proto-файл. 3. Указаем его на экране server_configuration для внутренних сборок браузера. Вставьте изображение
  16. Feature & Param: служебная страница browser://version?show-variations-cmd 18 --enable-features="Feature1<Trial1,Feature2<Trial2,Feature3" --force-fieldtrials="Trial1/Group1/Trial2/Group2" --force-fieldtrial-params="Trial1.Group1:p1/v1/p2/v2,Trial2.Group2:p3/v3/p4/v4"

    где Feature - название фичи Trial - название эксперимента Group - группа в эксперименте p* - название параметра v* - значение параметра --force-fieldtrials="translator/enabled_new/" --force-fieldtrial-params="translator.enabled_new:timeout/5000" --enable-features="TranslateServiceAPITimeout<translator"
  17. Feature & Param: cheat url 19 yandexbrowser://ftg? my_pet_experiment=group_name& enable-features=feature1,feature2& disable-features=feature3&

    param1=value1&param2=value2 study { name: "my_pet_experiment" experiment { name: "group_name" probability_weight: 1000 feature_association { enable_feature: "feature1, feature2" disable_feature: "feature3" } param { name: "param1" value: "value1" } param { name: "param2" value: "value2" } } }
  18. А где же монетка хранится и что такое источник энтропии?

    21 Монетка - это случайное число из промежутка [0..1) ассоциированное с именем эксперимента. На основе монетки происходит выбор группы эксперимента. 1. Хранить монетку может быть небезопасно и избыточно 2. Генерация монетки должна быть одинаковой от запуска к запуску 3. Необходимо равномерно распределять пользователей по группам Цель - не хранить значения монеток на диске

  19. А где же монетка хранится? 22 1. Генерируется источник энтропии

    - UUID, который хранится на диске 2. Берется hash от источника энтропии и имени эксперимента 3. Значение хеша переводится в значение от [0..1) Подробнее какой хеш и как переводить “An Efficient Low-Entropy Provider" - https://clck.ru/JKS8H.

  20. Выводы: какой же должна быть система экспериментов 23 1. Конфигурируемой.

    2. Использовать разные сущности для разработки и аналитики. 3. Калькулируемой. 4. Иметь инструменты для диагностики и тестирования. 5. Расширяемой (chromium variation service - https://clck.ru/JR4HU) Проводите эксперименты, анализируйте их и делайте приложения лучше!