Разработка
Масштабирование iOS в Bumble: вызовы
В статье мы расскажем о работе, проделанной в течение 2022 и 2023 годов и направленной на решение проблем масштабирования наших производственных приложений для iOS.
Введение
Эта статья — первая в серии из трех. В ней мы расскажем о работе, проделанной в течение 2022 и 2023 годов и направленной на решение проблем масштабирования наших производственных приложений для iOS.
Кто мы?
Bumble Inc. является материнской компанией Bumble, Badoo, Fruitz и Official.. Платформа Bumble позволяет людям строить здоровые и равноправные отношения, используя добрые связи.
Основанная генеральным директором Уитни Вулф Херд в 2014 году, платформа Bumble стала одним из первых приложений для знакомств, в центре которого стояли женщины. Она объединяет людей на уровне знакомств (Bumble Date), дружбы (Bumble BFF) и профессионального общения (Bumble Bizz). Badoo, основанная в 2006 году, является одним из пионеров веб- и мобильных продуктов для знакомств. Fruitz, основанное в 2017 году, поощряет открытое и честное общение с помощью игривых фруктовых метафор. Official — приложение для пар, которое способствует открытому и честному общению между партнерами, было основано в 2020 году.
Для кого это?
Эта серия статей в блоге адресована командам, работающим в масштабах, схожих с нашими. Итак, каков наш масштаб?
Масштаб в Bumble Inc.
iOS-разработка в Bumble Inc. точно не маленькая! У нас есть:
- Десятки инженеров
- Сотни модулей
- 100+ рабочих пространств с фичами
- Миллионы строк Swift, с примесью ObjectiveC со старых добрых времен 🙃
- Десятки тысяч строк кастомного инструментального кода
- Много модульности, причем довольно высокого уровня
Читателям может показаться, что это довольно большой масштаб. Однако в этой серии статей мы будем рассматривать Bumble Inc. как команду среднего масштаба. Почему же?
Команды «среднего» размера
Мы выбрали терминологию «средние», чтобы подчеркнуть «промежуточное» состояние, в которое могут попасть команды в iOS-экосистеме.
- С одной стороны, есть небольшие команды — стартапы или индивидуальные разработчики. Маркетинг Apple для разработчиков часто кажется странно сфокусированным на таких командах! Они очень довольны своим предоставляемым разработчикам опытом (а почему бы и нет!).
- С другой стороны, у вас есть самые большие имена в индустрии. Вы знаете их! У них самые большие штаты разработчиков, целые созвездия продуктов и миллионы и миллионы строк кода. Эти компании могут оправдать крупные инвестиции в инфраструктурные инструменты и часто являются создателями тех самых инструментов, которые мы будем обсуждать в этой серии.
А между ними находятся команды среднего уровня: хотя Bumble, конечно, не стартап и не инди-приложение, мы также не являемся одним из гигантских гигантов. И мы не одиноки: большинство наших коллег работают в таком же масштабе.
Быть в середине
Когда проекты увеличиваются от размера стартапа или инди-компании до такого среднего масштаба, возникает слишком знакомая ситуация: ранее идеальный опыт разработчиков Apple начинает давать сбой. Что мы под этим подразумеваем?
Модульность, время сборки, Xcode
Все достаточно просто: чем больше кода, тем больше времени требуется на компиляцию, чтение, сохранение и индексацию.
Те, кто работал с большими проектами в Xcode, знают, что по мере увеличения размера проекта его производительность снижается — время открытия рабочей области, операций с файлами и, конечно же, время сборки увеличивается! Модульность может смягчить эту проблему: достаточно хорошо структурировать код, и вы сможете увеличить распараллеливание и кэширование. Но модульность должна быть легкой — если при перемещении, разделении, добавлении и удалении модулей возникает слишком много сложностей, то это не сработает.
Конечно, вы можете создавать фреймворки и настраивать проекты в Xcode. Проблема возникает, когда эти операции начинают затрагивать больше, чем несколько модулей — тогда у вас проблемы. В Xcode нет инструментов для выполнения пакетных изменений проекта. К счастью, сообщество разработчиков предоставляет множество инструментов для работы с форматом .pbxproj. В Bumble Inc. мы написали инструменты на основе XcodeProj. Хотя это и разблокировало нас, но в то же время мы получили множество кастомного инструментального кода, который нужно было поддерживать, и который был настолько гибким, насколько хватало уже реализованных функций.
Со временем начинает казаться, что это вы работаете на формат проекта Xcode, а не наоборот!
Команда и сотрудничество
Масштабирование проекта — это не только увеличение количества строк кода, но и масштабирование самой команды. Поверхность рабочего проекта должна быть увеличена, чтобы вместить все большее количество разработчиков, работающих над кодовой базой.
И снова .pbxproj демонстрирует свои ограничения: файлы проектов представляют собой текст, но описывают сложный граф объектов, что делает их едва ли пригодными для редактирования человеком и содержат много избыточности. Конфликты при слиянии могут оставить вас с проектами, которые невозможно открыть, и то же самое относится к .xibs и .storyboards. В крайнем случае можно прибегнуть к помощи текстового редактора, но это вряд ли продуктивное решение.
Но это не только у нас — эти проблемы часто встречаются и у остальных:
- With Bazel we were able to reduce build times by 70% on clean builds
- Building Faster in iOS with Bazel
- Xcodegen vs. Tuist vs. Bazel — Comparing the 3 Tools to Supercharge Your iOS Projects
Что делать?
Как мы уже говорили, команды такого размера находятся в двойном положении: традиционный рабочий процесс, ориентированный на Xcode, замедляет их скорость, но они не в состоянии делать крупные внутренние инвестиции в инфраструктуру. Поэтому такие команды вынуждены делать прагматичный выбор из готовых инструментов и тщательно изучать свои возможности.
Таким образом, на ранней стадии этого проекта в начале 2022 года iOS Core Team в Bumble Inc. оказалась в подобной ситуации. В оставшейся части этой серии статей мы рассмотрим, какие решения мы рассматривали, что выбрали и как это сработало для нас.
Специфика — где мы были
Прежде чем продолжить, мы должны проанализировать, на каком уровне мы были как команда, приступая к этому проекту.
Несмотря на то, что мы достигли пределов наших существующих решений, мы смогли использовать их с большим успехом. У нас была хорошо выстроенная архитектура, большой объем модульности и хороший уровень унификации. Мы уже создавали шаблоны типов модулей и делились их общими настройками с помощью большой сети .xcconfigs. Как уже упоминалось, мы автоматизировали работу с модулями, разбирая и изменяя .pbxproj с помощью кастомных инструментов, созданных в XcodeProj.
В остальном мы были и остаемся почти полностью в монорепо и имеем концепцию «рабочих пространств фич» (feature workspaces), которая позволяла вести разработку в стиле плейграунда вдали от всей кодовой базы, особенно для SwiftUI. У нас было едва больше десятка сторонних зависимостей и мощная инфраструктура CI и тестирования.
В общем, у нас были средства, мотивы и возможности для того, чтобы кардинально изменить наш основной рабочий процесс. Но какое решение могло бы удовлетворить наши потребности?
Цели
Что же мы искали?
- Возможность удалить и/или значительно сократить объем нашего пользовательского инструментария
- Значительно уменьшить трение, связанное с модуляцией
- (В идеале) повысить скорость сборки или, по крайней мере, поставить себя в более выгодное положение
- Открыть двери для новых идей и рабочих процессов
- Сохранить как можно больше поддерживаемости и возможности внедрять новые фичи
- Возможность удалить .xcodeproj из репозитория 😉.
Решения
В ходе наших исследовательских проектов мы рассматривали три инструмента:
- Swift Package Manager — главный инструмент распространения кода для языка Swift
- Tuist — сторонний набор инструментов для автоматизации разработки
- Bazel — простой и полнофункциональный инструмент оркестровки традиционных сборок, изначально разработанный в Google.
Важно отметить, что эти инструменты не являются эквивалентными. У них нет строго совпадающих наборов функций. Однако все они решают наши задачи, хотя и по-разному.
Swift Package Manager (SPM)
SPM был первым инструментом, который мы исследовали, и он обладает определенным «авторитетом», так как сделан самой Apple. Начиная с Xcode 11, он полностью интегрирован в набор инструментов Xcode и не требует установки. Это означает, что с нашей стороны нет необходимости в непосредственном обслуживании. Это большое преимущество, поскольку мы предпочитаем использовать инструмент, а не поддерживать его.
Некоторые читатели могут быть удивлены включением SPM, и это, вероятно, потому, что он уже имеет имидж ориентированного на управление зависимостями от сторонних разработчиков, в духе старого доброго CocoaPods. Однако, хотя вы, конечно, можете брать зависимости с Github.com и так далее, SPM также поддерживает URL-источники для файлов. Поэтому мы можем так же легко подтягивать локальные модули из нашего монорепо.
После миграции всех модулей в SPM Packages вы будете очень близки к тому, чтобы вообще отказаться от использования .xcodeproj — хотя и не совсем (подробнее об этом позже). Итак, можем ли мы просто воспользоваться готовым решением?
Это де-факто инструмент, но подойдет ли он для наших нужд?
Tuist
В отличие от SPM, Tuist — это стороннее решение. Его первая версия была выпущена в 2018 году, а версия 1.0 — в 2019-м, поэтому он еще относительно новый. Однако за это время он уже получил большую поддержку со стороны сообщества и регулярно выпускает новые версии.
По своей сути Tuist — это генератор проектов, который использует эту функциональность для создания инструментария, ориентированного на потребности именно таких команд и проектов, которые есть у нас.
Смогут ли его функции быть достаточно привлекательными, чтобы предпочесть их блестящему решению Apple?
Bazel
Bazel — это совсем другое дело. Это полноценный многоплатформенный инструмент для оркестровки сборок. То есть он не только сторонний, не созданный Apple или командой Swift, но и вообще не ориентирован непосредственно на экосистему iOS! Сам движок Bazel должен быть объединен с правилами, необходимыми для сборки и упаковки конкретных исходных данных для сборки. Кроме того, для этого нужно выучить новый язык, хотя он, скорее всего, будет немного знакомым.
Несмотря на это, Bazel открывает большие возможности и обещает несколько очень впечатляющих вещей. Кроме того, это единственное решение из трех, способное обеспечить повышенную скорость сборки в первый же день. Но это также и резкий отход от традиционного пути Xcode.
Но будет ли вся эта мощь достаточной, чтобы оправдать свою стоимость?
Что дальше
В этом посте мы рассказали о том, как мы подошли к этому проекту, какие цели ставили перед собой и какие инструменты рассматривали. В следующем посте мы расскажем о самих исследованиях и о том, что мы узнали о каждом инструменте. До встречи!