Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Привет, Хабр! Меня зовут Сергей, я занимаюсь мобильной разработкой 13 лет и недавно стал руководителем разработки мобильного приложения «Пункты выдачи заказов» в Ozon. Невольно став сместителем существующего строя в проекте (фреймворки, технологии, подход), я стал часто слышать вопрос: «Почему вы отказались от Flutter?».
Слышал я этот вопрос прежде всего от разработчиков моей команды и соискателей на наши вакансии, потом во время доклада на эту же тему на конференции Panda Meetup, в конце концов, даже менеджер нашего проекта подошёл с вопросом: «Ну а всё же почему?». Настолько людей захватывает эта тема, что я решил поделиться развёрнутым ответом.
Начнём с ответа на вопрос: «Почему изначально был выбран Flutter ещё год назад?» Попробуем разобраться в технических нюансах.
Чем хорош Flutter?
Мультиплатформенность — то, чем Flutter подкупает прежде всего
Менеджеры всех времён недоумевали: зачем писать одно и то же под разные платформы (iOS, Android), а потом ещё и для Web и, возможно, для десктопа? Поэтому с незапамятных времен мир был наводнён различными средствами разработки, помогающими объединять разработку для всех платформ в одном проекте — на одной кодовой базе и даже одном языке программирования. Среди них были и даже остаются FireMonkey, Qt, Xamarin, React Native и тот самый Flutter, который во многом опережает своих предшественников: на нём можно писать неплохие приложения одновременно и под iOS, и под Android. Да, и кроме мобилок были попытки затащить в наш проект и Web на Flutter, но безуспешные.
Google-Contributed
Гигант настолько увлёкся своим детищем (ну да, я про Dart от Google), что выпустил целую операционную систему Fuchsia OS, интерфейс которой построен на Dart. Внушает и оптимизм за будущее Flutter, и страх за будущее Android.
Давайте заглянем под капот Flutter и обнаружим, что там находится язык Dart — тот самый, который Google изобрела в качестве замены JavaScript в браузерах, а затем он применялся в бэкенд-разработке, пока не стал частью Flutter. В новой среде разработки Dart был немного доработан, и, если говорить про Web, то компиляция происходит в язык JS, а если про мобилки — то в машинный код. Если первый случай теоретически может привести к потере производительности, то второй должен как минимум не уступать. На схеме ниже видно, за счёт чего Flutter опережает в быстродействии своих мультиплатформенных конкурентов-предшественников. Источник
Open source
Говоря про популярность Flutter, стоит отметить, что он открыт и бесплатен: если вдруг Google бросит проект, исходный код останется доступен всем — и вы сможете его поддерживать вместе с комьюнити.
Декларативный подход
Наибольшую популярность Flutter сыскал среди разработчиков благодаря декларативному подходу в реализации интерфейсов, и этот подход значительно ускоряет разработку.
Совместимость с Native
Дисклеймер: под Native в данной статье я буду иметь в виду нативные языки и фреймворки для разработки под iOS и Android.
Последним преимуществом Flutter можно выделить возможность затащить в проект код на Native. То есть, например, специфическое определение геолокации, которая работает по регионам, вы не найдёте из коробки среды, поскольку оно присутствует только на iOS и не было смысла затаскивать его во Flutter. Но не стоит расстраиваться — Flutter позволяет внедрять код, написанный на Swift, в виде плагина и использовать данную возможность, специфичную для iOS и только для iOS. Такая же возможность есть и у других платформ при работе с Flutter, поэтому тем, кто считает, что «Flutter не умеет всё» можно ответить: «А что не умеет — научим на Native».
Данной иллюстрацией пищевой цепочки мультиплатформенной разработки завершаю рассказ о преимуществах Flutter.
Я осознанно не стал упоминать о Kotlin Multiplatform Mobile (KMM) как о ещё более молодом конкуренте, поскольку для меня очевидно, что его развитие в скором времени приведёт Flutter к участи React Native и Xamarin, с которых я уже имел «счастье» переписывать приложения на Native. Думаю, сейчас, в 2022 году, ко мне бы не подошли с аналогичным вопросом о переписывании с React Native. Хотя раньше мне приходилось проходить тот же путь — доказывать бизнесу необходимость и целесообразность переписывания React Native-приложения на Native. Я думаю, что этот поток вопросов о Flutter не утихнет, пока Kotlin Multiplatform Mobile, вангую, — не вытеснит Flutter с пьедестала почёта. На сегодняшний день статистика на этот счёт пока молчит.
Чем же Flutter уступает Native?
̶N̶a̶t̶i̶v̶e̶ ̶k̶i̶l̶l̶e̶r̶ Google Killed
Даже если каким-то чудом KMM не станет вершиной мультиплатформенной программистской мысли, у меня для вас печальные известия: Google славится внезапным закрытием проектов, и Flutter в любой момент может занять топовое место на кладбище гуглопроектов. Правда, в какой-то момент корпорация, так же, как поступила с Dart, может внезапно воскресить Flutter и, например, начать использовать его для программирования чипов, вживляемых людям через прививки, будь то Pfizer или Спутник V. Хотя о чём это я? Неее, скорее всего, этим будет заниматься Google Daydream.
Dart так себе язык
Тут все будут ждать какое-то обоснование, но я просто собрал отзывы вкусовых предпочтений у разработчиков, которые не пожелали оставаться на Flutter. Перегруженный лишними конструкциями синтаксис, точки с запятой и так далее — просто исчадие Java. А Android-разработчики будто на Kotlin с Java побежали от хорошей жизни. А почему, собственно, KMM может опередить Flutter? Вот, например, давайте посмотрим на Dart: когда в него завезли null safety? Правильно, только весной 2021 года, а ведь это базовый механизм статической типизации. Сколько лет меняется Dart — и только сейчас в нём появилось то, что было доступно в первых версиях Swift и Kotlin семь лет лет назад. Зато есть подобие coroutines, что прекрасно для экс-бэкенд-языка.
Сообщество платформы
Конечно, прекрасно, что Flutter можно посмотреть в исходниках, как и увидеть, сколько issues сейчас открыто в официальном репозитории: их количество только растёт — это говорит о том, что команда пока не справляется с потоком ошибок. Например, только совсем недавно сделали, чтобы анимации не тормозили на iOS ¯_(ツ)_/¯
Фреймворки пока тоже сыроваты: при малейшем отклонении программы от обычного документооборота в сторону специфики железа писать вам и так и так придётся на Native. Например, с чем столкнулась моя команда: камера (сканер кодов — это основной функционал, очень критичный компонент для нашего приложения) тормозит и глючит с подсветкой. Когда мы начинали делать этот компонент, во Flutter ещё не было готового решения (сейчас оно существует, но за качество не ручаюсь). Ещё для сохранения состояния приложения использовался сторонний компонент Hive и в какой-то момент обновления библиотеки состояние приложения обнулилось: оказалось, что в компоненте уже известны несколько критичных багов, и почему-то их никто не стремится исправить. В остальном, после того как во Flutter, наконец, пофиксили проблемы с анимацией, кажется, можно «жить», если ваше приложение содержит простую функциональность.
Собственный UI, характерный для обеих мобильных платформ
Ранее я упоминал, что у Flutter свой собственный рендеринг — это означает, что поведение визуальных компонентов (курсора в поле ввода, контекстного меню, анимации, навигации экранов, и прочее) отличается от принятого на каждой из платформ. Всё это может несколько озадачить пользователя вашего приложения.
Инфраструктура
В поисках инфраструктурных решений как нативный iOS-разработчик я натыкался чаще всего на Stack Overflow, посвящённый проблемам с Flutter: сбою работы CocoaPods или fastlane при сборке проекта.
Если вы захотите завести автотесты, у вас также могут возникнуть препятствия. В Ozon принято использовать Appium: когда пытались завести его через специальный драйвер, то при тестировании приложения он постоянно отваливался. Если у вас есть какой-то положительный пример автотестирования, делитесь в комментариях, какой вы инструмент использовали и с чем сталкивались.
И всё-таки кому нужен Flutter?
Несмотря на некоторые негативные моменты, которыми Flutter озадачивает нашу команду на поддержке старой версии приложения до сих пор, на мой взгляд, эта технология хорошо подходит для решения некоторого круга задач:
Абсолютно бескомпромиссный документооборот (только, пожалуйста, без использования камеры).
Стартапы для прототипирования — тот класс проектов, в которых надо быстро проверить гипотезу, чтобы принять решение, развивать дальше продукт или выкинуть.
Разработка по DDD (уверяю, это был не наш случай).
Достоинства и недостатки Flutter (в сравнении с Native)
№ | Достоинства Flutter | Недостатки Flutter |
1 | Мультиплатформенность | Нестандартное поведение компонентов на платформах |
2 | Google-Contributed (поддержка IT-гиганта) | May be killed by Google (поддержка внезапно может прекратиться) |
3 | Dart компилируемый, хорошая производительность | Разработчики предпочтут Swift или Kotlin нежели Dart |
4 | Open source / freeware | Качество фреймворков пока оставляет желать лучшего |
5 | Декларативный UI | На Native теперь есть SwiftUI и Jetpack Compose, аналогичные Dart |
6 | Возможность совмещать с Native | Отсутствие специфических функций во фреймворках, приходится их писать на Native |
7 | Популярен, затмевает React Native | Может быть вытеснен Kotlin Multiplatform Mobile |
Мы всё взвесили — и решили переехать на Native
А теперь подойдём поближе к нашему проекту мобильного приложения для ПВЗ (пунктов выдачи заказов). С его помощью сотрудники ПВЗ выдают посылки, ищут заказы по номеру или штрихкоду, перемещают товары на полках, принимают возвраты, учатся на Ozon Learning и многое другое.
Итак, наступил момент, когда наш продукт из стартапа с документооборотом решил перерасти в долгоиграющий проект, бизнесу захотелось перейти от количественного к качественному: более нативного поведения и вообще, чтобы ставили только пять звёзд. Как убедить бизнес, что нужно всё переписать на Native? И вообще надо ли? А что будет с командой? Захотят ли спецы на Flutter возвращаться на старый добрый Native-стек?
План перехода на Native
Мы разработали план, чтобы не облажаться:
Составили роадмап разработки минимального функционала (соответствующего версии, которая была написана на Flutter).
Произвели поиск решений внутри компании и обнаружили достаточно мощное движение в поддержку Native и готовые компоненты, выделенные в отдельные SDK, что ускорит переписывание.
Продумали адаптацию команды: нам важно не растерять ценных сотрудников, хорошо знакомых с тонкостями проекта.
Перейдут ли с Flutter на Native разработчики?
Flutter, безусловно, искушает разработчиков тоже перейти на него и оставаться на нём, но можно принять меры в Native и вернуть их на светлую сторону.
Декларативный UI
И тут сам Flutter подсказал решение: он как катализатор развития мобильных платформ подтолкнул их к созданию альтернативных решений для Native — речь идёт о SwiftUI и Jetpack Compose.
Взгляните на листинги кода для интерфейсов: декларативный подход теперь доступен на Native, и он аналогичен таковому во Flutter, причём оценки аналитиков нашего и другого проекта компании показали возможность использования таких технологий.
Единое решение
Кроме того, было принято решение использовать единую архитектуру в мобильном приложении для обеих платформ, делать перекрёстное и межплатформенное ревью, чтобы идти в одном направлении.
Инфраструктура
Ну и наконец, проблемы с автотестированием просто исчезнут, так как даже внутри Ozon уже есть много опробованных технологий на Native. Отмечу, что 80% времени, отведённого на тестирование, мы тратим на написание автотестов, так что у нас нет исключительно ручных тестировщиков.
Заключение
Время покажет, насколько верным было наше решение. С начала переписывания прошло всего полтора месяца, и пока я могу похвастаться тем, что обе команды — и Android, и iOS — идут с опережением графика, согласно составленному роадмапу, несмотря на то, что технологии для разработчиков обеих платформ новые.
Из интересного замечу, что межплатформенное ревью, которое мы провели в начале года, позволило перенять опыт и лучшие практики команд каждой платформы. iOS и Andoid и правда выглядят как братья-близнецы, но при этом, в отличие от Flutter проекта, имеют собственные (платформенные) характеры.