Использование экспериментов для уверенного решения большого рефакторинга

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

К сожалению, поскольку наша страница поиска была написана с использованием в значительной степени неподдерживаемого фреймворка (Twitter's Flight), который не использовался где-либо еще на нашем сайте, она не могла извлечь выгоду из этих инвестиций в инструменты. и накопление институциональных знаний об использовании React. Коду страницы поиска также не хватало исчерпывающего набора тестов. Таким образом, часто было намного сложнее (читай: медленнее) работать с кодовой базой страницы поиска по сравнению с другими кодовыми базами аналогичного размера.

В начале 2016 года мы решили начать рефакторинг страницы поиска на Реагировать. Простой UX страницы поиска противоречит ее сложной реализации; Зачастую на странице проводятся эксперименты с многочисленными внешними командами, не говоря уже о различных настройках, ориентированных на регион и рынок. Эта сложность в сочетании с тонким тестовым покрытием означала, что любой существенный рефакторинг, вероятно, вызовет некоторые регрессии в поведении. Поскольку страница поиска находится в верхней части гостевой последовательности, мы должны были быть абсолютно уверены в том, что регрессия будет сведена к минимуму, чтобы уменьшить любое негативное влияние на наш основной бизнес. В этом сообщении блога мы рассказываем о том, как с помощью экспериментов мы смогли уверенно запустить отредактированную страницу поиска.

Введите ERF

Experiment Reporting Framework (ERF) - это внутренний инструмент, разработанный нашей командой Data Tools, который упрощает задачи настройки эксперимента, анализа данных и визуализации результатов. Это позволяет нам проводить сплит-тесты и анализировать влияние каждого лечения в соответствии с различными показателями, в том числе теми, которые связаны с нашим основным бизнесом. У нас также есть возможность сегментировать эти показатели по таким параметрам, как регион, страна, браузер и платформа; это оказалось бесценным для сужения регрессий, о чем мы поговорим позже. ERF используется практически во всех продуктах и ​​функциях, запускаемых на Airbnb.

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

Настройка

Как и в React, Flight инкапсулирует поведение в компоненты и устанавливает иерархию компонентов, а иерархия компонентов, представленная Flight, в значительной степени перекрывается с тем, что мы представляли в React. Это упростило процесс рефакторинга; Таким образом, наш подход заключался в том, чтобы повторно реализовать компонент Flight в React и провести сплит-тестирование между ними с помощью ERF.

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

С завершением создания строительных лесов и шимминга мы могли переходим к рефакторингу самих компонентов и их тестированию экспериментально.

Ловля регрессий

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

Листинговые карточки - один из самых сложных компонентов на странице поиска; за многими путями кода скрывается множество вариантов поведения, поэтому неудивительно, что рефакторинг не смог перенести некоторые варианты поведения. Разумеется, когда мы провели эксперимент, сравнивая исходную карточку с листингом и ее копию, подвергшуюся рефакторингу, мы увидели падение количества просмотров страницы с листингом со страницы поиска. Сегментация по платформам выявила интересную закономерность - провал был изолирован для платформ iPhone и Android:

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

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

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

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

Предостережения

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

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

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

Заключение

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