Вопросы по теме «Инструментация и качество данных»
Трекинг событий, naming conventions, data contracts, валидация данных — от качества инструментации зависит качество всей аналитики. На собеседовании спрашивают, как спроектировать систему событий для нового фичи, что делать при расхождении данных между системами и как обнаружить проблемы с логированием.
Всего в этом разделе 20 вопросов. Каждый — с правильным ответом и кратким разбором теории. Разбито на 4 части по 5 вопросов.
Вопросы 1–5 из 20
1Вы логируете событие `experiment_exposure` для A/B-тестов. Какой инвариант наиболее полезен для контроля качества данных?
AРаспределение вариантов должно быть строго 50/50 каждый день, иначе данные `experiment_exposure` некорректны
BОдин пользователь за время эксперимента должен получать ровно один вариант, а ключевые поля `experiment_exposure` обязаны быть заполнены
CСобытие `experiment_exposure` отправляется при каждом открытии экрана: чем больше отправок, тем точнее доли вариантов
DСобытие `experiment_exposure` логируется только при первом запуске приложения и далее не повторяется в течение всего эксперимента
Ответ: Инварианты для `experiment_exposure` должны ловить противоречия в назначении варианта и обязательные поля, а не требовать идеальной пропорции.
Главный инвариант данных эксперимента — стабильность присвоения варианта на пользователя: один и тот же `user_id` не должен встречаться в логе с двумя разными значениями `variant`. Это ловит баги рандомизации, кросс-девайс склейки и кеширования. Заполненность ключевых полей (`experiment_id`, `variant`, `user_id`) проверяется параллельно. Жёсткое требование 50/50 каждый день нереалистично — небольшие SRM на коротких окнах нормальны. Отправка при каждом открытии экрана раздувает объём, а отправка только при первом запуске теряет переназначения и долгосрочные эксперименты.
Подробный разбор → 2Вы описываете схему событий для `purchase_succeeded`. Как лучше хранить сумму покупки в свойствах события, чтобы избежать проблем качества данных при агрегациях?
AХранить `amount='1990 RUB'` строкой с символом валюты: значение сразу читается человеком в отчётах и интерфейсах
BХранить `amount='1 990'` строкой с разделителями именно так, как сумма отображается пользователю в интерфейсе приложения
CХранить `amount_minor=1990` числом в минимальных единицах и `currency='RUB'` отдельным свойством для последующих агрегаций
DХранить `amount=1990.0` числом с плавающей точкой и без отдельного поля валюты, а валюту определять по стране пользователя
Ответ: Для аналитики лучше хранить числовое поле и валюту отдельно, чтобы избежать парсинга и неоднозначностей в свойствах события.
Суммы в событиях лучше хранить целым числом в минимальных единицах валюты (копейки, центы) и валюту класть отдельным полем. Это исключает ошибки округления `float`, упрощает агрегации `SUM` и фильтрацию по валюте, и не требует парсинга строк в ETL. Строковые форматы вроде `'1990 RUB'` или `'1 990'` ломают арифметические операции и зависят от локали. Хранение `float` без валюты вынуждает определять её по косвенным признакам, что приводит к ошибкам у мультивалютных пользователей.
Подробный разбор → 3Какой санити-чек лучше всего подходит для поля валюты в событиях покупок с точки зрения инвариантов и качества данных?
AПроверять, что валюта строго равна `'RUB'`, и считать любое другое значение ошибкой данных независимо от контекста
BРазрешить любые значения валюты без проверки списка кодов: чем больше форматов, тем шире охват рынков в логах
CУдалить поле валюты совсем и хранить только сумму в минимальных единицах, договорившись о единой валюте платежа
DПроверять, что поле непустое и входит в список допустимых ISO-кодов; алертить на новые или неожиданные значения валюты
Ответ: Инвариант для перечислимого поля должен проверять непустоту и допустимый набор значений, иначе ошибки будут скрыты.
Санити-чек на поле валюты обычно опирается на whitelist: непустое значение из списка ISO 4217 кодов, поддерживаемых продуктом, и алерт на любое новое или неожиданное значение. Так ловятся опечатки, баги клиентов и расширение рынков, о которых аналитика ещё не знает. Жёстко фиксировать одну валюту нельзя — продукт может работать в нескольких регионах. Разрешать любые значения — открыть путь мусору. Удаление поля валюты ломает мультивалютные расчёты и привязывает данные к одному рынку без явного контракта.
Подробный разбор → 4Какие свойства полезно добавлять почти ко всем событиям, чтобы быстрее диагностировать проблемы инструментирования событий после релизов?
AДостаточно одного `user_id` в свойствах события: остальные поля раздувают объём и усложняют разбор инцидентов после релиза
BДобавлять `app_version` и `platform` к каждому событию, чтобы локализовать баги по версиям и окружению пользователя продукта
CДобавлять только `country` и `language`: эти поля задают сегмент пользователя без необходимости знать версию сборки или платформу
DУбирать поле `app_version` из событий: данные становятся единым массивом без сегментации по сборкам и проще ложатся в отчёт
Ответ: Поля версии и платформы в логировании помогают быстро понять, где именно сломалось инструментирование событий.
Базовый набор служебных полей в каждом событии — версия приложения, платформа и версия SDK или номер сборки. Это позволяет в первые минуты после релиза увидеть, в какой именно сборке поломалась отправка или появилась аномалия в метрике, и не тратить часы на корреляцию с релиз-нотами. Только `user_id` не даёт разрезать данные по сборкам. Только страна и язык — полезные сегменты, но не помогают локализовать инцидент. Удаление `app_version` лишает аналитику ключевого инструмента диагностики после релизов.
Подробный разбор → 5Вы хотите логировать применение фильтров в каталоге. Какой вариант лучше для таксономии событий и последующей аналитики?
AСоздавать отдельные события `filter_applied_color`, `filter_applied_brand` и так далее под каждый тип фильтра.
BЛогировать общее событие `user_did_something` и складывать все детали фильтра в одно текстовое поле.
CЛогировать единое событие `filter_applied` с параметрами вида `{filter: 'brand', value: 'nike'}` в payload.
DЛогировать событие `filter_applied` без параметров, а конкретное значение фильтра восстанавливать по скриншотам интерфейса.
Ответ: Стабильное имя события и динамические параметры в полях обычно лучше, чем плодить отдельные события под каждое значение.
Динамические имена событий раздувают таксономию и усложняют запросы и контроль качества данных. Единое событие с параметрами позволяет добавлять новые фильтры без взрыва числа имён. Такой подход проще валидировать и сравнивать между платформами. Текстовые поля и скриншоты плохо подходят для надёжной аналитики и автоматических проверок.
Подробный разбор → Другие темы: Продуктовая аналитика