Предлагаем продолжить добрую традицию Ask me anything на Хабре и поговорить про разработку Android-приложений. Сегодня и завтра Android-команда Badoo будет на связи и ответит на любые вопросы о разработке и тестировании приложений с многомиллионной аудиторией, даст советы начинающим и расскажет про особенности платформы. Если вы столкнулись с какой-то проблемой или у вас есть вопрос по теме, пишите нам!



Обещаем ответить на все комментарии первого уровня, которые появятся здесь до 16:00 17 июля по московскому времени, а по возможности — и на более поздние.

Немного фактов о нас. Badoo и Bumble — одни из самых популярных дейтинг-сервисов в мире: только в Google Play у нас 210 млн скачиваний. В Android-приложениях больше 1,3 млн строк кода. В Android-команде больше 20 разработчиков. Основной язык разработки — Kotlin, архитектурные паттерны — MVI и RIBs, база данных — SQLite.

Под катом — подробнее о нашей команде и о темах, на которые мы можем поговорить.

UPD: Мы завершаем AMA и прощаемся. Спасибо всем за вопросы!


С вами на связи


Иван Бирюков bivy


image

Моя айтишная история началась в 1997 году, когда я выиграл школьную олимпиаду. C тех пор понеслось. В Badoo я работаю семь с половиной лет. Сначала занимался Android-разработкой, потом построил команду мобильных архитекторов, разрабатывающую в том числе протокол коммуникации с сервером. Сейчас отвечаю за все нативные мобильные приложения — Badoo и Bumble для iOS и Android.





Анатолий Варивончик ANublo


image

Я работаю в команде регистрации Badoo два с половиной года. До этого жил и работал в Минске. Готов рассказать о регистрации и фотоверификации в приложении: как мы добились нелинейного флоу в регистрации и как используем нейронные сети в фотоверификации.







Аркадий Иванов arkivanov


image

Я в Badoo уже три года и девять месяцев, техлид чат-команды. До этого работал в Яндексе, а ещё раньше — в Mail.ru Group. Моё главное хобби — играть неоклассику на электрогитаре. Из профессиональных интересов — поддержка библиотеки Badoo Reaktive и моей собственной MVIKotlin. Готов ответить на вопросы об архитектуре, MVI, мультиплатформе, Rx.





Николай Чамеев lukaville


image

Я работаю в Badoo два года, в основном — над различной инфраструктурой для Android-приложений. Core team, участником которой я являюсь, в последнее время занималась увеличением скорости сборки приложений, инфраструктурой запуска тестов на CI, мониторингом и оптимизацией приложений (app start/ANRs/crashes).







Артём Ушаков temq91


image

Все полгода работы в Badoo я нахожусь в юните Revenue. В наши обязанности входят разработка и поддержка функциональности, тем или иным образом связанной с revenue: paywall, рекламные и платёжные SDK. До Badoo я работал в компании MERA. В последнее время интересуюсь DevOps (контейнеризация, Docker и т. д.) и билд-системами. Экспериментирую с Raspberry Pi 4: делаю из него домашний NAS.





Азат Хайруллин AzatKhairullin


image

Я работаю Android-разработчиком в Badoo около полутора лет. Сейчас в основном занимаюсь профилями пользователей и encounters — экраном с карточками. До этого работал в Biglion, а ещё раньше — фрилансил и жил на острове Панган. Немного играю в Hearthstone, интересуюсь Flutter.







Юрий Уфимцев yufimtsev


image

В Badoo я два с половиной года. Воплотил в жизнь дюжину фичей, последние полтора года тружусь в команде чата, используемого в обоих наших приложениях. До Badoo я руководил группой Android-разработки в Яндексе и создавал приложения с нуля в Rosberry. Был президентом омского клуба риичи-маджонга «Канчи ветров» (возможно, являюсь им до сих пор, но это неточно).







Темы, на которые мы можем поговорить


  • Архитектура наших приложений и сравнение архитектурных паттернов.
  • Как выстроен процесс разработки.
  • Как мы работаем с легаси-кодом.
  • Как устроен процесс тестирования приложений.
  • A/B-тесты в Badoo и Bumble.
  • Как мы работаем с дизайн-системой.
  • Карьера Android-разработчика.


Самые интересные вопросы и ответы с AMA на Reddit


Недавно мы устраивали сессию вопросов и ответов на Reddit вместе с англоязычной частью нашей команды — и получили 163 вопроса от пользователей. Некоторые из них мы перевели для читателей Хабра: надеемся, они станут поводом расспросить нас о чём-то подробнее.

Вопросы и ответы с AMA на Reddit

Какую архитектуру вы используете? Нравится ли она вам и что бы вы изменили, если бы могли? Какие уроки вы извлекли?


Жольт: Мы используем сильно переделанную версию RIBs (под «сильной переделкой» я подразумеваю «В этой ветке 871 коммит и 15 коммитов после uber:master»). Получилась древовидная структура, каждый слой которой можно взять и вставить в другое приложение со всеми связанными с ним ветками. В узлах дерева мы применяем паттерн MVI с реактивными биндингами. Мы довольны тем, что получилось!

Какие уроки мы извлекли. Activity — это неверная абстракция. Если хотите использовать компоненты многократно, то навигация не должна быть глобальной. Сильно помогает удаление из компонентов понятия экрана. Наличие определённой структуры для создания переиспользуемых компонентов очень помогает нам понимать код друг друга. Всю тяжёлую работу прячьте за абстракциями, чтобы клиентский код было легче писать и сопровождать.

Майкл: Недавно наша команда Revenue Team начала экспериментировать с новым подходом на основе MVI, который мы назвали SubFlow. Большое влияние на него оказал паттерн с акторами (как это видно на примере библиотек Play Framework и Vert.x). Изначально этот подход применялся нашей iOS-командой. Увидев, как он хорошо работает, мы решили тоже попробовать. Суть в разделении бизнес-логики на простые одношаговые акторы. Каждый актор/подпроцесс для выполнения следующего шага может запустить следующий подпроцесс в цепочке. Возможные варианты подпроцессов конфигурируются извне.

Нашей главной задачей было уменьшить сложность и громоздкость кода, а также обменяться опытом с iOS-командой. Работа ещё в стадии эксперимента, но результаты нам уже очень нравятся. К сожалению, код пока закрыт.

Наверняка у вас есть древний код. Как вы относитесь к рефакторингу старых решений, чтобы идти в ногу со временем? Если рефакторите, то как? У вас этим занимается специально обученный человек или целая команда?


Анатолий: Если при разработке новой функциональности приходится изменять уже существующий код, то мы можем вносить в оценку задачи рефакторинг старой части кода. Кроме того, если мы сталкиваемся с проблемами в кодовой базе, то обсуждаем с руководством выделение времени на рефакторинг. По умолчанию мы тратим на это около 20% времени. Рефакторить может кто угодно в зависимости ситуации, у нас нет для этого специального человека.

Антон: Я стараюсь соблюдать правило скаута: «Оставляй после себя код лучше, чем он был, когда ты его нашёл». Работая над фичей, которая затрагивает старый код, я стараюсь улучшить покрытие тестами; возможно, делаю небольшой рефакторинг, например разбиваю длинные методы. А для более масштабных переделок мы составляем конкретный план, выделяем на это время и определяем этапы.

Майкл: У нас есть части кода, написанные в далёком 2012 году. Мы оставили их нетронутыми, потому что было страшно менять их без покрытия тестами. То есть мы сначала улучшаем покрытие, в этом нам помогает наша замечательная команда тестировщиков, которая с помощью Calabash создаёт для нас end-to-end-тесты. Затем мы начинаем маленькими кусочками переписывать старый код, часто объединяя это с работой над фичами. Наконец, мы специально выделяем время на переписывание самых «плохих» частей. В соответствии с правилом команды Revenue Team мы тратим один день в неделю, чтобы держать под контролем технический долг, выбирая для этого какую-нибудь необычную задачу.

Какую БД вы используете в приложении?


Аркадий: Мы используем SQLite: либо базовый SQLiteOpenHelper, либо Room. Последний мы используем только в новых модулях, над которыми работаем в данный момент. Переводить на Room другие части приложения (например, чат), которые уже используют SQLiteOpenHelper, нецелесообразно.

Как вы относитесь к Annotation Processing?


Аркадий: Отрицательно. Плагины для компилятора — наше будущее!
Николай: Мы стараемся избегать обработки аннотаций и для тестовых сборок по мере возможности используем реализации библиотек обработки аннотаций с поддержкой рефлексии. Сейчас мы применяем обработку аннотаций для Dagger, Room и Toothpick.
Андрей: Apt годится до тех пор, пока это не kapt.

Проект сегментирован по странам? Как это сделано?


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

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

Ваш проект использует App Bundle? Какой был выигрыш в размерах .apk?


Николай: Да, мы используем App Bundle. Размер приложения с использованием App Bundle уменьшился примерно на 17%.

Андрей: Также мы применяем Dynamic Delivery и даже написали об этом статью.

Обсуждала ли команда миграцию на мультиплатформенный подход? На какой именно или почему нет?


Аркадий: Мы экспериментировали с Kotlin Multiplatform, у нас есть целиком написанный на нём внутренний проект, и мы обсуждали использование этой технологии в продакшене. В нашем основном проекте тоже есть несколько мультиплатформенных модулей, но сейчас они используются только в Android.

Для поддержки перехода мы создали Reactive Extensions-библиотеку Reaktive.

MVICore сейчас переводится на Kotlin Multiplatform.

Может ли команда рассказать о каком-нибудь маленьком изменении или новой фиче, которая продемонстрировала большие результаты?


Анатолий: Что касается фич, то мы реализовали в Badoo видеочаты и оптимизировали функцию отправки подарков. Раньше пользователю нужно было нажать на кнопку трансляции, затем на «Отправить подарок» и выбрать подарок. Целых три действия — и людям не было очевидно, что есть такая возможность. Поэтому мы добавили нижнюю панель с горизонтальным списком подарков, чтобы пользователи могли выбрать подарок одним нажатием и сразу же отправить его стримеру. На внедрение ушло около трёх дней, но позже мы получили значительное увеличение числа отправленных подарков.

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

Используете ли вы Android Jetpack, Fragments и Activities? Или что-то вместо них?


Жольт: Хороший вопрос!

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

LiveData: нет. Вместо MVVM у нас MVI, и мы разработали для неё собственный инструмент для автоматического определения области видимости — Binder. Сейчас он существует как часть нашей библиотеки MVICore, но мы планируем сделать его в виде отдельной библиотеки. Так будет универсальнее по сравнению с LiveData, поскольку в этом случае Binder можно будет использовать и вне контекста Android, причём очень легко (одна строка на Kotlin). Почитать об этом подробнее можно здесь и здесь. Действительно отличный инструмент. Попробуйте его.

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

Fragments: нет. С помощью RIBs мы создали что-то похожее на глубоко вложенное дерево фрагментов, но гораздо лучше. Также мы без каких-либо хаков решили проблему безопасного внедрения конструкторов вроде Fragment Factory на этапе компиляции. Фреймворк собирает компоненты за вас, но вы говорите ему, как это делать.

Почему мы пошли своим путём, а не следуем общепринятым практикам? Дело в том, что этот процесс начался много лет назад. Задолго до наступления эры Jetpack мы пытались идти по «пути Google» и в результате обожглись на Fragments. Ушли от этого, стараясь понять, какая альтернатива подойдёт нам лучше всего. Часто мы были одними из первых, кто внедрял у себя новую технологию (в 2016-м мы попробовали «чистую» архитектуру и RxJava, в 2017-м — Kotlin и MVI на основе Redux), и подобных инструментов, фреймворков и библиотек было не так уж много. К моменту анонса Jetpack мы уже вложились в собственный технологический стек. И в целом он вполне нас устраивает в сравнении с общепринятыми подходами.

К слову, мы используем Room, и лично меня очень интересует Jetpack Compose.


Пожалуйста, оставляйте вопросы в комментариях первого уровня, чтобы нам было легче их найти.

Ask me anything — поехали!