Привет, меня зовут Санжар, я iOS-техлид в Beeline Казахстан. В iOS-разработке 6+ лет, сейчас занимаюсь развитием мобильного приложения «Мой Beeline».  В статье поделюсь опытом становления супераппа «Мой Beeline». Это один из наших флагманских продуктов, мы уделяем ему много времени и внимания. Я расскажу о гипотезах и экспериментах, о разработке и способах решения проблем. Напомню, что я сотрудник казахстанской компании, то есть рассказываю про казахстанский суперапп и смогу ответить на вопросы о нём. По части российского приложения «Билайн» я не эксперт. Сперва давайте определимся с понятиями. Я слежу за внедрением супераппов несколько лет и вижу, что многие считают супераппом приложение, в котором можно делать вообще всё, что что может прийти в голову. Другая часть людей считает, супераппом приложение, в котором есть функции из области финансов, досуга и лайфстайл.  По-моему, оба варианта неполные. В моем понимании, приложение становится супераппом, когда оно предоставляет несколько функциональностей, выходящих за рамки своего профиля. Например, банковское приложение можно считать супераппом, когда кроме финансовых функций в нем есть и другие, напрямую не связанные с банковской деятельностью. Дальше я буду говорить о супераппе именно с этой точки зрения. Заметил, что некоторым людям в принципе не нравится пользоваться супераппами, им удобнее скачивать отдельное приложение для  каждой задачи. Много комментариев об этом было в статье про суперапп от «Тинькофф банка». Мое предположение — скорее всего, это связано с неудобством самого приложения, непродуманностью пользовательского опыта. До 2020 года кроме телеком-услуг (просмотр детализации по аккаунту, смена тарифа, обмен минут на гигабайты и т. д.) в нашем приложении были только онлайн-платежи (пополнение баланса, оплата коммунальных услуг и некоторые другие). В начале пандемии мы поняли, что пора менять подход к развитию приложения. В мае 2020 года мы начали развивать традиционное приложение в сторону супераппа. Офисы Beeline были закрыты, но компании как-то нужно было продолжать предоставлять селф-сервисные операции: замену сим-карт, покупку номера или его перенос между операторами мобильной связи. Также у нас самая большая клиентская база в Казахстане, нам было важно ее сохранить. Чтобы привлечь новых и удержать текущих клиентов, мы решили расширять спектр услуг. С этого момента мы начали разработку и внедрение селф-сервисных операций и запустили процесс трансформации приложения в суперапп. Сейчас через наше приложение можно купить или портировать номер, заменить номер или сим-карту (online-sim и eSIM). Но для всех этих манипуляций важно обезопасить пользователя — сделать так, чтобы данными не могли завладеть мошенники. Для этого мы добавили идентификацию пользователя через сканирование государственных документов и верификацию по биометрическим данным.  Кроме основной функциоинальности, стандартной для телеком-компаний (детализация трафика, настройка и смена тарифов,операции с минутами и гигабайтами), у нас доступно подключение разного рода непрофильных услуг: например, сервиса «Яндекс.Плюс» и подобных ему. Из смежного — классические финансовые операции: совершение различных платежей, переводов и оплат по номеру телефона или карты, QR-коду, настройка автоплатежей, возможность выводить сумму баланса на банковский счет онлайн или через банкоматы и почтовые отделения. Сейчас в нашем приложении можно послушать 20 млн музыкальных треков, посмотреть фильмы и сериалы, поиграть в десятки игр, изучить широкий ассортимент линейки смартфонов и роутеров, сразу оформить на них заказ, оплатить или выбрать рассрочку и тип доставки. А для решения любых проблем с работой приложения или сервисов есть чат-бот и онлайн-чат. Поэтому мы теперь, скорее, digital-компания на базе телекома, а не просто оператор связи. Наше приложение сочетает много разнообразных технологий и возможностей:  Искусственный интеллект: чат-бот Дана, витрина, основанная на BigData & Machine Learning, биометрия. Финансы: онлайн-платежи, переводы по номеру телефона, операции по QR-коду, рассрочка, кредиты. Агрегаторы: игры, фильмы, сериалы, новости, музыка. Онлайн-магазин гаджетов: покупка смартфонов, роутеров. Телеком-услуги: конструктор тарифов, мобильная связь, смена тарифов, детализация, семейные пакеты. Сейчас мы в процессе расширения. В суперапп будет добавлена геймификация — получение пользователями бонусов и плюшек за разные действия. Мы будем дарить трафик, звонки и смс за входы в приложение, совершение определенного количества платежей за месяц и т. п. Это важно, чтобы повышать вовлеченность пользователей.  На главную страницу хотим добавить агрегатор новостей, чтобы пользователи получали доступ как к локальным, так и зарубежным новостным порталам. Сделаем так, чтобы пользователь мог настроить подборку и категории новостей под себя.  Появятся образовательные продукты для детей и взрослых. Например, планируем кое-что для изучения языков, сервисы по здоровью, возможность облачного хранения данных и удобного взаимодействия с ними. Еще в планах расширение аудитории. Мы хотим, чтобы супераппом могли пользоваться не только абоненты Beeline Казахстан, но и другие люди. Также работаем над офлайн-функциональностью, возможностью пользоваться какой-то частью сервисов без подключения к интернету. Когда компания решает переходить на суперапп, это значит, что она готова вкладываться в новые технологии и эксперименты. Разработка новых функций и их добавление в приложение требует больше усилий, чем допиливание и обновление одной и той же функциональности.  Фичи Например, наша команда активно следит за появлением новых технологий от Apple и Google. И как только появилась возможность, в ходе улучшений UX мы одними из первых в казахстанской разработке добавили бесшовное подключение eSim и сделали так, чтобы новая симка добавлялась или заменялась по одному клику. Это экономит время пользователя на чтение инструкции и пошаговое выполнение действий. Но не всегда мы сразу внедряем любые новшества. К примеру, мы думали о разработке виджетов, но отказались от этой идеи. С одной стороны, пользователи могли бы при помощи виджета следить за статистикой подключенного тарифа, это удобно. Но также это означает, что они будут реже заходить в приложение и не увидят новые функции, которые мы внедряем. Например, некоторые пользователи никогда бы не узнали, что можно поменять физическую симку на eSIM или восстановить номер без похода в офис, а значит — не смогли бы сэкономить на этом время.  Новые технологии Иногда для супераппа нужно добавить функциональность, в которой у тебя нет экспертизы. В этом случае компании часто начинают партнерство с кем-то, а то и просто находят и покупают подходящий технологический стартап, чтобы использовать его технологии и разработки. Мы пошли по первому пути. Начали сотрудничать с компанией Verigram в рамках улучшения продуктов по биометрии и интегрировали их решение в свои продукты. У нас не было сложностей с интеграцией, но приложение почти в два раза увеличилось по размеру из-за добавления сразу двух SDK (один для считываний данных документа, второй для проверки «живости»: живой ли человек сканирует лицо). Через полтора года мы вместе значительно улучшили проект, но в итоге приняли решение развиваться самостоятельно.  Собственная разработка После квартала активной работы внутренней команды биометрии SDK обновился и начал использоваться сразу во всех наших приложениях, в том числе во флагманском «Мой Билайн». Результаты внутренней разработки были отличные: увеличилась конверсия успешных сканирований, заметно уменьшились объемы фрода. Сейчас у команды Биометрии бэклог на год вперед с очень амбициозными планами. Например, мы хотим значительно уменьшить занимаемую SDK память. Кросс-командная работа Когда-то в «Моем Билайне» была проблема с добавлением новых функциональностей в определенную веб-страницу: нужно было учитывать тип url, от которого зависит, какие cookie-данные передавать или какие hook'и им отлавливать. Решили проблему так: теперь заранее скачиваем настройки, в которых хранится список cookies и hooks для каждой страницы. Это дает массу плюсов. Например, можно не ожидать деплоя бэка и подготовить отправку данных и отлавливание нажатия кнопок, в любой момент менять, удалять, добавлять различные данные и действия на веб-странице. Быстрое внесение изменений без необходимости в релизе Когда функциональность приложения разрастается, а команда увеличивается не так быстро, начинаешь смотреть в сторону технологий, которые помогут уменьшить время будущих доработок или изменений в том или ином флоу. Так у нас появилась идея о Backend For Frontend (BFF), Server Driven Design (SDD). Естественно, когда ты не стартап, а приложение с 3,5 млн MAU, не должно быть кардинальных изменений, но как минимум на один флоу мы хотели попробовать. Вот что вышло.  Когда пользователь кликает на кнопку, отправляется запрос, что начинается такой-то процесс/флоу. В ответ бэк присылает нам JSON, структуру которого мы пытались сделать максимально простой и понятной: — pageType: “SCREEN” | “REQUEST”. Первый говорит, что это страница для отображения, второй — что в этом окне перед открытием нужно отправить запрос; — displayType: “BOTTOB_PAGE” | “FULL_PAGE”. Первый говорит, что это динамическое окно, которое всплывает снизу вверх, второй — что его нужно отобразить как целостное окно; — url: когда pageType=”REQUEST”. Используется, чтобы понять какой запрос нужно отправлять; — elements: [UI components]. Список компонентов, которые нужно отобразить. Компонентов пока немного. Отправляется его тип, по которому вставляется настроенный компонент, например, font, color, alignment и т.д. Но этого достаточно, чтобы протестировать гипотезу быстрого изменения с наименьшими усилиями. Правильно рассчитывать время  При использовании некоторых фреймворков и технологий надо учитывать, что для получения разрешения от их владельцев вам может понадобиться больше времени, чем вы думаете. Поэтому нужно закладывать больше времени на вещи, которые не зависят от вас. Например, так произошло у нас с Apple, когда мы получали разрешение подключения абонементов бесшовного eSIM. Сотрудник, который этим занимался, на полпути ушел из компании, забыв передать общение другому коллеге. Чтобы разобраться во всем этом, ушла пара месяцев. Технология eSIM, о которой я упомянул, — это фреймворк CoreTelephony. По нему можно узнать данные об операторе, чтобы, опираясь на них, предоставлять дополнительные сервисы. Например, можно ли использовать VoIP, поддерживается ли eSIM на данном устройстве и т. д. Подключение этого фреймворка для eSIM довольно быстрое: буквально в несколько шагов можно импортировать фреймворк, проверить поддержку eSIM на устройстве, вызвать метод с параметрами адреса сервера оператора и id-шку симки — и готово. Дальше открывается нативное окно настройки в виде bottom sheet, чтобы дать согласие на подключение. Поэтому на взаимодействие со сторонними лицами и вендорами нужно брать время на разработку с запасом. Технические цели: рефакторинг, автоматизация, улучшения кодовой базы и упрощение разработки Сейчас у нас закладывается отдельное время для техцелей. Мы рефакторим легаси-код, избавляемся от некоторых зависимостей, добавляем анимации, следим за утечками в памяти, берем на анализ новые технологий или фичи, о внедрении которых будем думать. Важно закладывать на это время, чтобы продвигаться технологически.  Например, одни из ключевых и самых прибыльных разделов в приложении — это «Смена тарифа» и «Переподключение». Поэтому мы уделяем им много времени. Наша команда аналитиков обзванивает клиентов и собирает обратную связь о том, все ли понятно в разделе, мы проверяем разные гипотезы и разный дизайн, проводим опросы об интуитивности интерфейсов. Так разрабатывается новый или дорабатывается текущий дизайн. И да, на это уходит много времени, но оно того стоит. Когда команда разработчиков растет, появляются и другие задачи. Например, нужно следить, чтобы не было 100500 иконок для одной кнопки «Назад». Для исключения подобных проблем мы начали внедрять UI-kit (к этому приходят многие крупные компании, и на «Хабре» есть много статей об этом). Сейчас мы в процессе перехода и уже внедрили его для цветов, шрифтов и иконок. Мы решили использовать генератор кода Swiftgen, удобные и привычные enum-чики, а так же различные extensions. Есть еще некоторые buttons, bottom sheet, alerts и небольшие модули в виде ввода пин-кода, запроса на использования локаций, камеры и т. д. Но по плану, еще много чего нужно перевести в компоненты, например различные UITableViewCell, UITabBar, etc. Исторически сложилось, что у нас было сразу два менеджера зависимости: CocoaPods и SwiftPackageManager (SPM). Так вышло, потому что популярные библиотеки (например Firebase) еще не перешли полностью на стабильную SPM. Когда мы убедились, что можем полностью перейти на SPM без проблем и потерь, сразу сделали это. Статей о плюсах и минусах обоих менеджеров тоже много, но в нашем случае минус был двойной, так как нужно было сначала обновить одну (CocoaPods), потом вторую (SPM). Мультиязычность  Еще одна из популярных проблем в мобильной разработке — это локализация. Каждый решает ее по-своему. Одно из самых популярных решений — создать файлы для каждого языка внутри приложения и постоянно их обновлять. Тут важно не забыть добавить для каждого файла новый текст, не забыть обновить перевод во всех файлах. У этого решения есть минус. Если, скажем, была какая-то опечатка в тексте перевода, то пользователю будет нужно заново обновлять всё приложение.  Мы пошли другим путем. При загрузке приложений файлы с переводом обновляются по REST API. В реализации это все лишь один класс с несколькими методами.  Первое — загрузка json-файла с параметрами для нужного языка. Второе — открываем файлы с переводом (../lang-(language).json) через OutputStream (привет, Toll-free bridging). Вносим изменения через JSONSerialization, и закрываем его.  После этого мы получаем обновленные тексты, которые можно в любой момент поменять в admin-панели. Метрики  Мы используем «Яндекс.Метрику». В целом, не составит труда добавить еще десятки сервисов для отправки ивентов. Для отправки сервиса мы используем протокол с одинаковыми параметрами и методом, который каждый модуль отправки ивентов должен настраивать под себя, а один общий struct принимает этот протокол и собирает нужные данные. В этот struct мы можем добавить любой сервис отправки ивентов или изменить текущий. Рекомендации по удержанию пользователей на стабильнои версии Для этого мы внедрили следующую фичу: каждый раз, когда пользователь заходит в приложение, отправляется запрос в Backend о текущей версии приложения. В ответ мы получаем простенькую модельку, в которой есть рекомендуемая и минимальная версия, url, и статус. У статуса может быть три типа состояний. Если статус UP_TO_DATE, то у пользователя ничего не происходит, он дальше пользуется приложением.  Если статус UPDATE_RECOMENDED, мы отображаем пользователю (не сразу, а в определенный момент) bottom_sheet, в котором есть рекомендация по обновлению + кнопка «Обновить», которая ведет на страничку нашего приложения в AppStore. Там же есть вторая кнопка «Подробнее», которая ведет на веб-страницу с описанием обновления.  Если статус UPDATE_FORCE, мы сразу перенаправляем пользователя на страницу с растянутой на всё окно bottom_sheet. Он не свернется, пока приложение не обновят. Этот метод мы применяем у пользователей с очень старой версией приложений. Например, если у пользователя стоит версия 6.4.2, а у нас уже вышла 7.2.8. В заключении хотелось бы еще раз отметить, что при разработке супераппа в первую очередь нужно закладывать больше времени на какую-либо фичу. И что минимизация цены ошибки является важным показателем при разработке фичи с новой функциональностью в супераппе. Этого можно достичь через спланированный тайм-менеджмент и продуманную декомпозицию задач.  И конечно, важно не забывать документировать всё, хотя бы в коде, так как новая фича может быть непопулярным методом разработки в вашем кругу.  Еще очень важно, чтобы все в команде хотели работать по новому подходу, так как незаинтересованные сотрудники могут быстро перегореть в ходе разработки. Подходите к разработке нового функционала «с холодной головой», и это точно окупится.   iOS TeamLead