Jetpack Compose та SwiftUI. Чи пошкодувала наша команда про вибір «модних» мобільних технологій

Усі статті, обговорення, новини про Mobile — в одному місці. Підписуйтеся на телеграм-канал!

Привіт, мене звати Сергій Неруш, я керую командою мобільної розробки Android-застосунку AlphaNovel від venture builder SKELAR.

Два роки тому ми почали створювати новий продукт: маркетплейс новел і коміксів для читачів і письменників з усього світу. Отримавши нагоду будувати розробку з нуля, ми вирішили звернутися до найновіших технологій у мобільній розробці — Jetpack Compose для Android та SwiftUI для iOS, у той час, як більшість розробників уникали їх через новизну.

2021 рік і жодного відомого нам кейсу використання Jetpack Compose та SwiftUI у продакшені. Проте ми все ж вирішуємо братися за найновіші технології.

У цій статті я розповім, як ми наважились обрати непопулярні тоді рішення, чого очікували та чи виправдались наші сподівання. Насамкінець дам поради, які, сподіваюсь, полегшать майбутній вибір моїм колегам.

Як все починалося

Нещодавно я поспілкувався з декількома розробниками, які досі не використовують Jetpack Compose. На запитання «чому?» вони називають ті ж аргументи, через які й ми вагалися на старті розробки.

Тоді, у травні 2021-го, ми запускали новий проєкт після довгого ресьорчу. Розробку застосунків починали вдвох — я розробляв Android-застосунок, а мій колега Влад Хамбір будував iOS. При виборі таких архітектур та інструментів як MVI, Clean Architecture, Coroutines/Flows, Hilt для Android та MVVM+С, Combine для iOS для нашого проєкту «з нуля» у нас не було жодних вагань. Але з UI все було не так однозначно.

В Android-розробці на той час всі говорили лише про Jetpack Compose. В iOS-розробці також був свій новатор — SwiftUI. Спільнота розробників пророчила, що за цими технологіями майбутнє — Declarative UI, Stateless (майже) UI layer, Unidirectional Data Flow — ці концепції обіцяли покращити життя мобільних розробників.

От тільки ми не знали жодного продакшн-проєкту на базі Jetpack Compose та SwiftUI.

Прийшов час обирати

Всі переваги та недоліки попередніх підходів ми знали. А ось які очікування мали щодо Jetpack Compose та SwiftUI на старті.

✅ За:

  • Declarative UI та його наслідки (Stateless UI, Unidirectional Data Flow). Нам здалося, що це банально простіше та зрозуміліше. До простоти та зрозумілості ми прагнули і зі старим підходом, проте нові технології закладали ці принципи на рівні фреймворку.
  • Краща актуальність нас, як розробників, і нашого проєкту. Ми повірили, що за декілька років використання цих технологій стане новим стандартом. Як колись відбулося з переходом від Java -> Kotlin та Objective-C -> Swift.
  • Простіший найм в майбутньому. Якщо технології дійсно стануть новим стандартом, за рік-два це стане «green flag» для нових розробників.

❌ Проти:

  • Технології «сирі». На той момент Jetpack Compose знаходився в беті, а SwiftUI лише починав бути схожим на робочу технологію з релізом версії 2.0. Звичайно, ми готувалися до великої кількості багів.
  • Багато функціонала все ще не реалізовано в фреймворках, тож його потрібно буде дописувати самим, або ж писати окремі екрани застосунків без використання цих технологій.
  • Поганий performance. Завжди очікуєш, що нова технологія навряд чи відразу буде класно оптимізована. На Android я спробував тестово написати UI до найскладнішого екрану, і він явно підлагував.

Очікувані недоліки були дуже вагомими. Але ж ви знаєте — якщо чогось дуже хочеш, то знайдеш цьому виправдання.

«Так, дійсно, фреймворки виглядають сируватими, але ж ми не планували реліз вже через місяць, то, мабуть, до моменту релізу все стане стабільнішим», — цитата інженера, який дуже хоче Jetpack Compose.

«Так, не весь функціонал, що нам потрібен, є в нових фреймворках. Але є можливість розробити таку архітектуру, яка надасть можливість у будь-який момент повернутися до UIKit», — цитата інженера, який дуже хоче SwiftUI.
«Ну так, щось підлагує трохи UI, але ти подивись — в конкурентів так само, а то й гірше», — цитата вже обох інженерів.

Звичайно ж, ми переконали себе та команду та вирішили взятися за нові фреймворки.

Що з цього вийшло

Сьогодні Android-застосунок на 99,9% побудований на Jetpack Compose. Також, ми використовуємо Single Activity та Jetpack Navigation. Буду чесним — Jetpack Navigation для Compose —не найзручніша технологія. По стандарту, всі параметри, що ви передаєте між екранами, мають бути примітивами, а в ідеалі String.

Тому доведеться застосовувати декілька костилів вишуканих інженерних рішень, щоб мати змогу передавати об’єкти. А от MVI ідеально підійшов під Compose.

iOS — всі екрани написані на SwiftUI. З UIKit ми використовуємо лише навігацію. Кожен наш екран — це UIViewController, який містить у собі SwiftUI View. Тобто навігація виконується між UIViewController-ами, які використовуються як контейнери для SwiftUI-контенту.

Це вирішує питання з обмеженими можливостями SwiftUI-навігації та надає гнучкості у виборі підходу для реалізації екранів.

Якщо проєкт є складним — ми б радили робити архітектуру схожу на нашу, з використанням UIKit контейнерів. Якщо ж твій проєкт iOS 16+, можна взагалі забути про UIKit.

Загалом, ми прийшли до висновку, що використовувати SwiftUI варто лише в проєктах iOS 14+ (перша версія iOS 13 зовсім сира). А також памʼятати, що не завжди SwiftUI workaround написаний для iOS 15, буде так само працювати для iOS 14.

Ну, і головне — що сталося з нашими очікуваннями?

  • Розробка основної версії застосунку відбулася на 30% швидше, ніж при застосуванні попередніх підходів.

Jetpack Compose та SwiftUI надзвичайно пришвидшили нас. Це було неочікувано — адже недоліки, до яких ми готувались, мали б нас значно сповільнити. По-перше, ми планували витрачати час на дописування ще нереалізованих у підході рішень.

По-друге, зовсім новий підхід до побудови UI просто вимагає часу на його вивчення. Натомість команда зекономила третину часу.

  • Declarative UI та його наслідки.

Простота, яку дають фреймворки, є однією з причин пришвидшення розробки. Я впевнений — спробувавши декларативний UI, повертатись ви не захочете.

  • Краща актуальність і простіший найм.

Знання Jetpack Compose та SwiftUI все частіше зʼявляється у вакансіях. Можливо, просто зараз вони ще не стали стандартом, але точно рухаються в цьому напрямі. Коли ми розширювали команду та наймали інженерів як у iOS, так й у Android команди, саме Jetpack Compose та SwiftUI стали «магнітом» у вакансії для всіх кандидатів.

  • Не справдилося й очікування про «сирість» технологій — до сьогодні ми не стикались із серйозними багами (або ж ми ще не знаємо про них 🙂).

Звісно, баги зустрічались, але не більше ніж у попередніх підходах.

  • Нереалізований функціонал.

Дійсно, коли ми лише починали розробку у 2021 році, ми б точно погодились із цим твердженням. Проте з часом функціонала ставало все більше. Сьогодні всі бізнес-задачі, що ставить перед розробкою продуктова команда, ми реалізуємо новими фреймворками.

На iOS 95% проблем зі SwiftUI стосувалися кастомізації списків та поганої гнучкості ScrollView. Але всі проблеми можна вирішити та навіть обійти, якщо ваш застосунок не є клієнтом для читання книг, де ScrollView є досить важливим компонентом.

Якщо ви гадаєте, що відсутність якогось функціонала є аргументом, що не варто і чіпати нові фреймворки, то от вам історія Android-проєкта. Як я писав вище, наш проєкт — це маркетплейс новел і коміксів, тож наші користувачі читають просто у застосунку. Відповідно, найголовніший екран для користувача — екран із текстом. Текст в книжках — це HTML, але Jetpack Compose не вміє працювати з ним 🫠

Така серйозна проблема пофіксилась за 10 хвилин — ми просто використали стару технологію TextView. Використання попередніх View в Jetpack Compose реалізовано надзвичайно зручно. Тож насправді не було жодної задачі, яка виявилась для нас mission impossible.

  • Поганий performance. Талановиті інженери в Google та Apple не сиділи, склавши руки. За цей час фреймворки дуже добре оптимізувались. Так, декілька разів доводилося витратити день-другий, щоб оптимізувати найскладніші екрани, але це ж вимагали й попередні підходи.

Висновок

На сьогодні обидві платформи на 100% задоволені вибором на користь Jetpack Compose та SwiftUI. Всі наші позитивні очікування справдились, а негативні виявились зовсім не критичними.

Неочікуваний бонус — декларативний UI пришвидшив нас десь на 30%. Маючи вибір, до старого підходу ми точно не захочемо повертатись.

Сподіваюся, хтось з вас, хто ще не використовує ці технології, впізнав свої очікування, які ми мали 2 роки назад, і після цього таки наважиться спробувати. Наостанок дам кілька рекомендацій:

  1. Скоріш за все, ви вже знаєте, але нагадаю — SwiftUI та Jetpack Compose можна інтегрувати екран за екраном, а не відразу переписувати все.
  2. Як почати вчити? Jetpack Compose — це просто офіційна документація. Google дуже добре постарались. Прочитавши її, та пройшовши декілька їхніх Codelabs, ми вже чітко розуміли, що треба робити. iOS — є дві класні книжки від Ray Wenderlich Team — книга 1, книга 2 та Open Source документація з великою кількістю прикладів.
  3. Якщо шукаєте проєкт-приклад для Jetpack Compose, то рекомендую звернути увагу на цей. Він найбільше схожий на справжній проєкт, а не на штучний приклад, в якому все ідеально. Його пише експрацівник Google, дуже багато ми підгледіли саме там.
👍ПодобаєтьсяСподобалось11
До обраногоВ обраному5
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Сергій, чи можеш все ж відповісти чому не Flutter?
Бо схоже на те що тримати 2 команди через різні технології і писати один і той самий код двічі не дуже продуктивно і швидко.
Якщо знову з нуля запускати продукт ти розглядав би Flutter?

За мого не дуже великого досвіду з Flutter — він створює більше проблем аніж користі у великому проді (для MVP ок, але не більше).

Натив виграє у перформансі, зручності залучення нових членів команди, та коли мова йде про фішки платформи.

Якщо кортить тримати єдину кодову базу, то краще вже винести БЛ, та тримати її на Swift чи Kotlin.

А так — не про проблема написати код двічі для різних платформ. Це лише швидка копіпаста. Основна робота у більшості випадків — вигадати/створити логіку. А флаттер це буде, чи 2 різні нативи — пофіг

Писав був проект на SwiftUI для iOS 13/14, було боляче, дуже допомогла бібліотека SwiftUIX.

Дякую за рекомендацію.

Скільки часу пройшло від початку розробки, коди ви зрозуміли, що не прогадали з технологіями? Бо я тільки цього року перейшов на Compose і ось після майже півроку воно мені не заходить і я б залюбки повернувся б на звичайний view.

Гадаю, десь 2-3 місяці. Щойно ми закінчили розробку базової версії додатку. Вже тоді зрозуміли, що впорались значно швидше, серйозних проблем не зустріли, і що нові фреймворки нам дуже сподобались. Якщо не секрет, які ви для себе знайшли недоліки в Compose порівнюючи з View?

Читабельність коду. 10 років всі вважали, що розділяти верстку і ui логіку — це правильно. А тут вже виявляється, що ліпити все в коді — це круто. Жахливе превью. Ну і постійні зміни в компоузі, часто навіть не нагуглиш як що правильно зараз використовувати (наприклад, pager з tabrow).
Так, є моменти, які зробили простіше, ті ж windowInsets, зміна теми і тд, але чого це не можна було нормально додати до view?

Дякую, Павло. Дуже цікаво було дізнатись аргументи «проти» від людини, яка дійсно використовує Compose. Підтримаю, спочатку також було незвично, що тепер все «в одній купі». Згодом звик, а потім почав бачити в цьому лише переваги. Це поєднання значно пришвидшує, і (на мою суб’єктивну думку) виглядає значно простіше. Хоча тут варто відмітити — я був великим хейтером саме XML. Мені ця концепція здавалася дуже дивною. Писати щось в XML, щоб пізніше це зпарсилося у View класи і саме з ними ти вже повинен працювати. Навіть Anko виглядав більш логічним, бо пропускав етап написання XML і дозволяв одразу створювати View (хай пробачать мене програмісти, які переписували проект, коли Anko зробили deprecated).
Стосовно превʼю. Можливо я вже забув що там з XML (останній лейаут писав 2 роки назад), або ж бачу лише переваги в Compose:
1) Зʼявився вибір. Можна взагалі не малювати превʼю, якщо воно не потрібне, або ж намалювати все, що прийде в голову (на будь-якому фоні, в будь-якій кількості, будь-якого розміру, в поєднанні з будь-чим).
2) При правильній побудові Composable буде одна функція, яка приймає весь стейт екрану. Це дозволяє просто змінюючи цей обʼєкт отримувати превʼю в будь-якому стейті. Тобто можна створити декілька Preview функцій і вже маємо превʼю в стані загрузки, помилки, відсутності даних і т.д.
3) Ми зараз розробляємо нормальну підтримку для Foldables та Tablets. Створили 1 аннотацію @ComplexPreview, яка одразу створює превʼю Phone, Phone Landscape, Foldable, Tablet, Tablet Landscape. Верифікувати UI тепер значно швидше. Проте, можливо, вже і в XML є можливість виводити одразу багато превʼю.
4) Live Edit. Змінив UI логіку і вже одразу бачиш зміни в превʼю.

«чого це не можна було нормально додати до view» — цілком можливо, що підтримувати та додавати щось нове стає все складніше. Підходу скоро буде 15 років. Також, команда Android чітко вказує, що їхній вектор на майбутнє — це Compose. Думаю, саме туди і буде інвестуватись все більше ресурсів на розробку нового.

Я вважаю, що писати нові проєкти на нових технологіях — це найбільш правильне рішення. Усі розмови про те, що «ця технологія ще сира» — це просто заїжджені штампи, за якими ховається небажання вивчати нове. За свою 11-річну кар’єру я надто багато разів чув, як «сирими» нові технології називали люди, які їх навіть не спробували.

Так було і зі Swift. Я пам’ятаю, як на фоні розповідей про «сирість технології» у 2015 році ми зарелізили застосунок на Swift, і єдиною проблемою, з якою зіштовхнулися, була необхідність перевести код на Swift 3 у 2016 році. Зате цей досвід допоміг мені знайти роботу. До 2016 року у мене в портфоліо було вже 4 проєкти на Swift, і я отримав пропозицію роботи на проєкті, написаному на Swift.

Те саме стосується SwiftUI. Хтось з 2019 року не втомлюється розповідати, які ці технології «сирі», а хтось тим часом здобуває в них досвід.

До речі, окрім двох книг зі SwiftUI від Kodeco (колишній Ray Wenderlich), зазначених у статті, хочу порадити також книгу від objc «Thinking in SwiftUI».

100% погоджуюсь! Тим паче, якщо нові, круті, хоча і трохи сирі технології не «драйвити», то так і будемо використовувати 10-річні артефакти і залишатись на тому ж рівні розробки. Також, дякую за рекомендацію по SwiftUI!

Цікава стаття, дякую!
Як щодо флатеру? Не розглядали один декларативний кроссплатформний UI?

Дякую, Кирил.
Коли проект тільки починався, в команді вже були iOS та Android розробники. Тому питання щодо кросплатформи навіть не піднімалось. Якби найм в команду відбувався «з нуля», гадаю, на Flutter та React Native точно звернули б увагу та розглянули.
Також, перед початком розробки ми спробували реалізувати невеличкий проект на Kotlin Multiplatform. На той момент він нас не дуже задовольнив і ми вирішили поки рухатись без нього.
Взагалі, буду чесним, ще роки 2 тому я досить скептично відносився до кросплатформи. Аргументуючи це тим, що таких розробників було знайти складніше, і що «серйозний» додаток точно треба писати нативно (думка кожного нативного розробника :) ). Зараз же розробників більше, а аргумент про «серйозний» додаток взагалі абсурдний. Facebook, Instagram, Shopify, eBay — супер успішні продукти які або частково, або повністю написані на кросплатформі. Та і зустрічав декілька React Native додатків на які дивився і думав, що я тут би «попотів» те саме зробити нативно. Тому зараз, особисто мені, кросплатформа виглядає крутим рішенням, яке повністю покриє вимоги більшості бізнесів.

Підписатись на коментарі