Как Aviata и Chocotravel перешли на другой бэкенд
Intro.
Всем привет. Меня зовут Мендигарин Ернар, я работаю Android разработчиком в объединенной компании Aviata-Chocotravel. В этой статье расскажу, как мы с командой решили мигрировать процесс бронирования на Kotlin-Multiplatform Project (КМПП). Я не буду заострять внимание на конкретной реализации КМПП, а поделюсь опытом, полученным при миграции в эту технологию.
History.
Компании Chocotravel и Aviata до февраля 2018 года существовали отдельно друг от друга и конкурировали между собой за звание лучшего онлайн-трэвел агентства (далее ОТА) в Казахстане.
После объединения многим стало ясно, что процессы в компании схожи. Поиск авиабилетов, процесс бронирования, возвраты, обмены — всё было взаимосвязано. Тогда в компании решили, что нужно создать единую точку входа для всех процессов, откуда будут браться предложения от провайдеров для покупки авиа- и ж/д билетов. Единый бэк. Единая архитектура. Единая Платформа.
До объединения каждый сайт и мобильные приложения обращались к своему бэку — на тот момент это был монолит.
После объединения была создана новая команда — «Платформа». Она стала той самой единой точкой входа для обеих витрин — Авиаты и Chocotravel.
Такой подход давал возможность развиваться каждой витрине по отдельности, независимо друг от друга. Но угнаться за развитием авиа-индустрии и технологий нелегко. Новые релизы, фичи, изменения в логике приводили к увеличению багов и крашей. Приходилось менять старые процессы и создавать новые. Это оказывало огромную нагрузку на все отделы — от операторов службы поддержки, которые не всегда могли уследить за нововведениями до бухгалтеров, у которых не бились отчеты. Все это происходило из-за того, что у каждой витрины были свои ошибки, валидации, процессы и логика. Мы понимали, что наилучшим решением проблемы будет отказ от лишней прослойки — монолитов. Сделать так, чтобы каждая витрина обращалась напрямую к «Платформе».
Главный вопрос — «Когда?» Мы запланировали этот переход в начале 2020 года. Но нас тормозило то, что при переходе нам пришлось бы заморозить все процессы, улучшения, фичи на неопределенный срок. Все классы должны были переписаться на другую структуру, которая приходит от «Платформы», а не от монолита — сайт, мобильная версия сайта, Android, iOS. 8 платформ должны были приостановить все задачи на этот переход.
Planning.
Хватит истории. Давайте теперь сосредоточимся на самом переходе и решении использовать Kotlin-Multiplatform. В течение 2-3 месяцев мы планировали использовать эту технологию. Однажды мы уже пытались взяться за нее — для интеграции одного сервиса в приложении. Но мы решили отложить интеграцию, так как в продуктовых командах не было времени на изучение и настройку проекта.
Позднее нам сообщили о том, что у нас будет целый квартал для перехода на другой бэк. Мы с Android и IOS разработчиками не стали долго думать и решили — это идеальный момент, чтобы попробовать внедрить единую точку входа для всей бизнес логики приложений: Android Aviata, Android Chocotravel, iOS Aviata, iOS Chocotravel.
Why.
Почему Kotlin-Multiplatform, а не другие мультиплатформенные решения? Для нас было важно сохранить UI/UX наших приложений. Нативность каждой платформы никто и никогда не отменял. Если в приложении что-то резко меняется — это может вызвать негатив у пользователей.
How.
Изучение Kotlin-Multiplatform у нас заняло 1 спринт. За это время мы очень много читали документацию, смотрели туториалы, разные доклады с Youtube по мультиплатформе, пытались писать пет проекты. Когда мы только начали пытаться что-либо писать, было очень мало информации в интернете, а документация была запутанной. Совет для тех, кто хочет попробовать — просто скопируйте настройки Gradle и пакеты в каком-нибудь проекте, который написан на мультиплатформе.
Libraries.
При настройке проекта у нас часто возникали вопросы по поводу библиотек, которые могли бы решить проблемы. Библиотек было множество, как от самих JetBrains, так и от инди-разработчиков/команд. Но самый главный вопрос состоял в том, как мы будем ходить в сеть. Тут уже разработчики из JetBrains подумали за нас и создали библиотеку Ktor(Retrofit/Alamofire), которая очень хорошо справляется со своими обязанностями. Есть еще одна библиотека, которая хорошо взаимодействует с Ktor для сериализации данных — kotlinx-serialization. Для ассинхроннщины мы использовали корутины + flow, помимо стандартной библиотеки котлина stblib. Из сторонних разработчиков использовали библиотеку Klock от korlibs (в тот момент еще не вышла библиотека от Jetbrains kotlinx-datetime). Вначале мы подключали и другие библиотеки для проверки, но с каждым разом находили более изящные решения. На более позднем этапе в нашей мультиплатформенной библиотеке осталось 4 библиотеки, 3 из которых предоставляются разработчиками от JetBrains.
Architecture.
Итак, проект настроен и все библиотеки были подключены. Мы, истинные разработчики по заветам дядюшки Боба, начали внедрять чистую архитектуру с data + domain слоями. Вопрос состоял в следующем: подключать еще один слой, как presentation в виде класса ViewModel, или остановиться на domain-e, и пусть каждая платформа реализует по своему, без навязывания к конкретной реализации.
Вначале для каждой фичи мы создавали отдельные ViewModel-ки и подстраивали под необходимый нам экран с нужными юзкейсами. Уже на поздних стадиях миграции мы решили убрать эту возможность и оставить библиотеку до domain слоя. Два основных момента, которые сыграли в этом роль:
- при таком подходе для каждой платформы было бы по 2 VM на экран, что уже считается анти-паттерном;
- любая платформа при возможности может перейти на другой архитектурный шаблон без привязки к одному виду.
Troubles.
Нет дыма без огня. При разработке мы сталкивались с разными траблами. Но самая главная проблема заключалась в правильной настройке Gradle. Если нам, как Android разработчикам, Gradle был знаком, то настройка мультиплатформенной библиотеки для нас стала настоящим вызовом. Gradle больше не казался только добавлением сторонних библиотек, настройкой разных buildTypes/flavors и апания minSdkVersion c 19 -> 21. Теперь это была отдельно живущая система, с разными тасками, кастомными плагинами, билд-скриптами, сорсетами, и другими настройками. У нас ушло 2 недели на то, чтобы настроить более-менее рабочую версию библиотеки, которая бы запускалась как для Android, так и для iOS. Под конец мы уже начали опускать руки, но тут к нам на помощь пришли разработчики из TouchLab. Они поделились старт-китом на гитхабе, который можно было импортнуть к себе и начать писать первые строки кода.
Publishing.
Для нас было важно иметь возможность расширения библиотеки. Мы хотели максимально раздробить разные фичи на разные модули, чтобы наша библиотека не была в виде монолита. Тогда каждая фича не будет зависеть от других факторов.
На данный момент у нас в публикации core библиотека, у которой есть базовые классы, extesions, util, работы с датами и всего прочего. Библиотека авторизации, библиотека airflow — процесс от поиска до бронирования, библиотека payment -— процесс оплат. Для Android библиотеки лежит в Jfrog Artifactory, для IOS подспеки и сам фреймворк лежит в приватном гитлаб репозитории.
Nowadays.
Android приложение Авиаты уже 4 месяца находится на проде с КМПП модулем. iOS Авиаты запустили на прод в конце октября 2020 года. Android Chocotravel находится в активной разработке. В ближайшем будущем состоится переход на КМПП iOS Chocotravel. В общей сложности переход приложения Авиаты Android ушло 6 недель, не считая времени на разработку мультиплатформы. Переходом занимались 2 разработчика. IOS Авиаты — 4 недели, было задействовано 4 с половиной разработчика. Понадобилось больше времени и больше людей, потому что помимо перехода мы обновляли дизайн, добавляли важные компоненты. Плюс все задействованные iOS разработчики ранее никогда не работали в авиа-сегменте.
Future.
Мы не хотим останавливаться! Мы получили фидбэк от iOS-еров о том, как можно улучшить некоторые вещи для комфортной работы с библиотекой. Будем дальше её развивать и внедрять эту технологию в другие слои приложения, такие как личный кабинет, возвраты и обмены. Многие вещи, которые делаются на стороне клиента, мы хотим вынести в библиотеку, чтобы был One source of truth.
Полезные ссылки:
- https://kotlinlang.org/docs/reference/multiplatform.html — Оффициальная документация по мультиплатформе.
- https://github.com/AAkira/Kotlin-Multiplatform-Libraries и https://libs.kmp.icerock.dev — Список мульти-платформенных библиотек.
- https://github.com/touchlab/KaMPKit — Старт-кит от компании TouchLab.
https://t.me/pokerash — телеграмм аккаунт Ернара, если у вас остались вопросы.