slavachernikoff
Architectures of ReactNative, Xamarin, PhoneGap and Qt

Updated 6 months ago

Distributed under CC BY-ND licence

Binwell’s Guide

Архитектуры ReactNative, Xamarin, PhoneGap и Qt

Анализ архитектур популярных мобильных кроссплатформенных фреймворков для iOS, Android и Windows UWP.

Об авторе и компании Binwell

В компании Binwell (https://binwell.com) мы создаем мобильные приложения и облачные сервисы под ключ с использованием Xamarin и Azure. Осуществляем разработку полного цикла: бизнес-аналитика, проектирование, дизайн, кодирование, тестирование, публикация, развитие. Ключевыми направлениями деятельности являются: реализация комплексных решений на основе облачных и мобильных технологий, а также реализация интеграционных проектов на базе облачной платформы Azure. Сфокусированы на стеке .NET, являемся Microsoft Azure Partner и Xamarin Certified Partner.

Вячеслав Черников является руководителем отдела разработки в компании Binwell, а также Microsoft MVP и Xamarin Certified Developer. В прошлом был отмечен статусами Qt Certified Specialist, Qt Ambassador и Nokia Champion. В сферу mobile пришел в 2005 в качестве автора и редактора портала Ladoshki.com, был руководителем проекта iPAQ Choice (проект HP для владельцев наладонников iPAQ) и с 2008 года вернулся к программированию, сфокусировавшись на Qt. Участвовал в более чем 40 проектах мобильных приложений и игр для iOS, Android, Windows, Symbian, Maemo/Meego в качестве разработчика, аналитика и проектировщика. Автор популярных статей о Xamarin и Mobile DevOps.

Введение

Архитектуру программных продуктов можно сравнить со скелетом, расположением и связями внутренних органов человека. Именно поэтому в реальных проектах архитектуре следует уделять особое внимание. Чтобы “организм” имел возможность гармоничного роста и длительного существования.

В нашем руководстве мы рассмотрим архитектуры популярных кроссплатформенных мобильных фреймворков, проведем их сравнение и определим, для какого класса задач или команд подходит тот или инструмент.

Самих фреймворков сейчас существует очень много, но с архитектурной точки зрения они в основном аналогичны PhoneGap, ReactNative и Xamarin, поэтому мы остановимся на этой тройке лидеров. Qt мы добавили в обзор, так как нас часто об этом спрашивают активные Qt-разработчики или те, кто раньше с ним работали и слышали о поддержке iOS и Android.

В качестве целевых платформ мы остановимся на iOS, Android и Windows UWP.

Ключевые вопросы, на которые мы постараемся ответить в данном руководстве:

  1. Какой инструмент выбрать для кроссплатформенной разработки с учетом имеющихся компетенций (команда), наработок (существующий код) и целей проекта?
  2. Как устроены кроссплатформенные фреймворки с точки зрения архитектуры, и как они взаимодействуют с iOS/Android/Windows UWP?

Наш обзор ориентирован в первую очередь на технических руководителей, которые определяются с тем, стоит ли использовать кроссплатформенные инструменты и если использовать, то какой из них лучше всего подойдет для долгосрочного развития продукта. Также данное руководство может быть рекомендовано всем интересующимся кроссплатформенной разработкой мобильных приложений.

Приятного чтения!

1. Нативные и кроссплатформенные инструменты разработки

Исторически на рынке компьютеров всегда была конкуренция и каждый производитель предоставлял оптимальный набор так называемых «нативных» (родных) инструментов для разработки приложений под свои операционные системы и устройства. «Нативные» средства разработки обеспечивают максимальную производительность и полный доступ к возможностям операционной системы.

Однако часто оказывалось, что эти инструменты были несовместимы друг с другом не только на уровне языка разработки, принятых соглашений и архитектур, но и на уровне механизмов работы с операционной системой и библиотеками. В результате для реализации одних и тех же алгоритмов, пользовательских или бизнес-сценариев требовалось написать приложение для нескольких сред на разных языках программирования. Например, если надо поддерживать 2 платформы, то требуется увеличение трудозатрат и команды в 2 раза. Плюс в 2 раза больше бюджетов на поддержку и развитие. Можно добавить, что во многих компаниях уже скопилась большая база кода, который также хотелось бы унаследовать в новых решениях.

Вторым важным моментом является наличие необходимых компетенций (знаний и опыта) внутри команды – если их нет, то потребуется время на обучение.

Для того, чтобы решить обе этих проблемы, на рынке появились инструменты кроссплатформенной разработки, предлагающие:

  • максимизировать общую базу кода на едином языке программирования, чтобы продукт было проще разрабатывать и поддерживать;

  • использовать существующие компетенции и специалистов для реализации приложений на новых платформах.

Так как языков программирования (и сред) сейчас наплодилось очень много (и специалистов, владеющих этими языками), то и инструментов для кроссплатформенной разработки существует изрядное количество. В данной книге нас интересуют только инструменты для создания мобильных бизнес-приложений, поэтому в следующих главах мы подробнее разберем как они работают. А пока чуть детальнее каждый из плюсов кроссплатформенной разработки:

Общая база кода. В зависимости от выбранного инструмента разработчик сможет шарить между платформами: ресурсы приложения (картинки, шрифты и прочие файлы), логику работы с данными, бизнес-логику и описание интерфейса. И если с ресурсами и логикой (обработки данных и бизнес-) все довольно просто, то вот с интерфейсом следует быть осторожнее, так как для каждой из платформ есть свои рекомендации и требования.

Использование существующих компетенций и команды. Здесь стоит учитывать не только язык программирования, но и понимание механизмов работы операционных систем iOS/Android/Windows, а также набор дополнительных библиотек и инструментов разработки.

Итак, «нативные» инструменты предоставляются самими владельцами экосистем и позволяют получить максимум из возможностей целевой операционной системы, имеют полный доступ к родным API, оптимальную производительность и требуют отдельной команды разработки под каждую платформу.

Кроссплатформенные фреймворки позволяют сократить трудозатраты и ускорить выпуск приложений в том случае, если требуется поддержка нескольких платформ одновременно, и имеются (или развиваются) необходимые компетенции. В долгосрочной перспективе кроссплатформенные решения помогут сэкономить приличное количество человеко-часов, но для этого стоит учитывать особенности выбранного инструмента.

2. Архитектура iOS/Android и нативные API

Главный принцип, лежащий в основе кроссплатформенных решений - разделение кода на 2 части:

  • кроссплатформенную, живущую в виртуальном окружении и имеющую ограниченный доступ к возможностям целевой платформы через специальный мост;

  • нативную, которая обеспечивает инициализацию приложения, управление жизненным циклом ключевых объектов и имеющую полный доступ к системным API.

Для того, чтобы связывать между собой мир “нативный” и мир “кроссплатформенный”, необходимо использовать специальный мост (bridge). И как мы увидим в главе 3, именно bridge и определяет возможности и ограничения кроссплатформенных фреймворков.


ВАЖНО: Использование bridge всегда негативно сказывается на производительности за счет преобразования данных между “мирами”, а также конвертации вызовов API и библиотек. Сам по себе “кроссплатформенный” мир имеет сопоставимую с “нативным” производительность.


Итак, все кроссплатформенные приложения обязаны иметь нативную часть, иначе операционная система просто не сможет их запустить. Поэтому давайте рассмотрим подробнее, какие системные API и механизмы предоставляются самими iOS, Android и Windows.

2.1 Нативный iOS

Начнем мы наш обзор операционных систем с iOS, которая в свою очередь основана на Mac OS X, созданной из NeXTSTEP OS, являющейся полноценной Unix-системой. Поэтому iOS стоит воспринимать как полноценную Unix-систему без командной строки.

Нативные интерфейсы низкого уровня в iOS реализованы по аналогии с Unix (для С). Для iOS-разработчика выбор языков ограничивается Objective C и Swift, ведь именно для них реализованы нативные инструменты и API. Также можно использовать С/С++, но это будет либо от острой необходимости (есть существующие наработки), либо из сильного любопытства, так как потребуется высокая квалификация и написание приличной базы вспомогательного кода. Общая архитектура iOS представлена ниже.

Дополнительно на схеме мы отметили подсистемы, которые имеют значение для кроссплатформенных фреймворков:

  • WebKit используется в гибридных приложениях на базе PhoneGap или аналогов для запуска приложений и фактически выступает средой выполнения веб-приложений;

  • JavaScript Core используется в ReactNative и аналогах для быстрого выполнения JS-кода и обмена данными между Native и JS;

  • OpenGL ES используется в играх и приложениях на Qt/QML или аналогах для отрисовки интерфейса;

  • UIKit отвечает за нативный пользовательский интерфейс приложения, что актуально для ReactNative и Xamarin.

Как видим, из коробки iOS предоставляет готовые интерфейсы для Objective C (Swift работает в качестве надстройки), плюс имеются механизмы для кроссплатформенных HTML/JS-приложений (WebKit, JavaScriptCore). С iOS API на уровне системных вызовов могут работать любые фреймворки, поддерживающие Unix-вызовы, но для полноценного взаимодействия с Objective C API из других языков будет необходимо написать специальные обертки.


ВАЖНО: В iOS недоступна компиляция Just In Time, кроме компиляции JavaScript с помощью WebKit. Это связано с тем, что в iOS закрыт доступ к записываемой исполняемой памяти (writable executable memory), что не позволяет генерировать исполняемый код динамически.


Ввиду ограничений iOS, все приложения, требующие JIT (кроме JavaScript) должны быть скомпилированы в машинный код (Ahead Of Time compilation, AOT), что может стать неожиданностью для разработчиков Java и .NET. Ограничение это продиктовано повышенными требованиями к безопасности и производительности.

2.2 Нативный Android

Android также является Unix-системой и большей частью основан на Linux со всеми вытекающими плюсами и минусами. Однако уши Linux не сильно торчат у Android, так как поверх ядра ОС создана своя инфраструктура, включающая виртуальную машину Java (Java Virtual Machine, JVM) для запуска приложений. JVM выступает посредником между пользовательским кодом и набором системных API, доступных для Java-приложений. Поддержка языка Kotlin является надстройкой над той инфраструктурой, которая доступна Java.

Как видим, в Android разработчику доступно сразу целых 2 подсистемы: Native Development Kit (Android NDK) и Android SDK.

С помощью NDK можно получить доступ к низкоуровневым механизмам Android. Разработка ведется на С/С++.

При использовании Android SDK разработчик оказывается внутри Java-машины Dalvik (или Android Runtime, ART) и имеем только те возможности, которые предоставляет Java API.

Связующим звеном между библиотеками низкого уровня (на C/C++) и инфраструктурой Java выступает специальный JNI bridge (Java Native Interface), который и позволяет двум мирам взаимодействовать друг с другом. JNI выступает единым и универсальным связующим звеном, однако как и любой мост ведет к падению производительности, если начинает использоваться неэффективно.


ВАЖНО: JNI снижает производительность приложений, когда большой поток команд и данных передается через мост


Помимо JNI bridge, в архитектуре Android также стоит обратить внимание на наличие подсистем WebKit (для PhoneGap), OpenGL ES (для Qt и игр) и View System (грубо, =аналог iOS UIKit, для ReactNative и Xamarin) аналогичные модулям в iOS. Однако в сравнении с iOS ограничений меньше - можно использовать JIT не только для JavaScript, но и других языков, плюс нет жесткой привязки к JS-движку.

Сам по себе Android до недавнего времени использовал JIT для Java-приложений, что не самым лучшим образом сказывалось на производительности. Начиная с версии 5.0 в Android добавили механизм AOT-компиляции байт-кода (как часть ART), что улучшило поведение программ, однако не сняло ограничения JNI bridge. Забегая вперед отметим, что JNI будет использоваться в приложениях на Xamarin и Qt.

2.3 Нативный Windows UWP

Напоследок давайте рассмотрим архитектуру Windows UWP, которая является самой всеядной и предоставляет большое количество различных интерфейсов и механизмов взаимодействия, включая Windows Bridges (https://developer.microsoft.com/en-us/windows/bridges)

Помимо традиционных API для C++/C#, Windows UWP также предоставляет механизмы работы с JavaScript на базе движка Chakra, который используется в Edge. Microsoft поддерживает open source версию ReactNative на Windows UWP: https://github.com/Microsoft/react-native-windows

Также система имеет WebView и подходит для приложений в духе PhoneGap. Реализации OpenGL ES нет, вместо нее доступен только DirectX. Qt работает, но с большими ограничениями.

В качестве “диковинных” решений в Windows также доступны различные технологии бриджинга, например для запуска self-hosted сайтов (https://developer.microsoft.com/en-us/windows/bridges/hosted-web-apps) в качестве локальных приложений, а также классических десктопных Win32-программ или даже iOS-приложений (https://developer.microsoft.com/en-us/windows/bridges/ios).

Для нас же важно, что Windows UWP обеспечивает все необходимые механизмы для работы PhoneGap, ReactNative и Qt. Если рассматривать “Классический Xamarin”, то он работает только в iOS/Android (в Windows C#/.NET и так являются родными), однако библиотека Xamarin.Forms отлично функционирует поверх родных Windows UWP API, но о ней мы поговорим в Главе 3.5.

3. Архитектуры кроссплатформенных фреймворков

Итак, мы рассмотрели архитектуры iOS, Android и Windows UWP. Как вы могли заметить, все операционные системы имеют те или иные технические возможности по запуску кроссплатформенных приложений. Самое простое с технической точки зрения - использование WebView, которое есть у всех ОС (актуально для PhoneGap). Вторым вариантом является использование механизмов низкого уровня вроде OpenGL ES и языка C/C++ - это позволит разделять между проектами большинство логики (в играх или Qt), но будет ограниченно работать (или не работать) на Windows UWP. Если же вам будет нужен полностью нативный пользовательский интерфейс и нативная производительность с минимальными накладными расходами, то здесь начинают задействоваться системные API верхнего уровня - такой подход реализуется только в Xamarin и ReactNative.

Чтобы лучше понять возможности и ограничения каждого из фреймворков, давайте рассмотрим, как архитектурно они устроены и какие из этого следуют возможности и ограничения.

3.1 PhoneGap

Решения на базе PhoneGap используют WebView и являются достаточно простыми с точки зрения реализации - создается небольшое нативное приложение, которое фактически просто отображает встроенный веб-браузер и single-page HTML. Нет никаких нативных контролов и прямого доступа к API - все интерфейсные элементы внутри веб-страницы просто стилизуются под родные. Для доступа к системной функциональности подключаются специальные плагины, которые добавляют JS-методы внутрь веб-браузера и связывают их с нативной реализацией на каждой платформе.

Как видим, PhoneGap позволяет разделять практически весь код между платформами, однако все еще требуется реализация нативной части на Objective C и Java (и C# для Windows). Вся жизнь приложения проходит внутри WebView, поэтому веб-разработчики почувствуют себя как рыба в воде. До тех пор, пока не возникнет потребность в платформенной функциональности - здесь уже будет необходимо хорошее понимание iOS и Android.

Также PhoneGap (он же Apache Cordova) используется в популярном фреймворке Ionic, который предоставляет большое количество готовых плагинов для системной функциональности.


ВАЖНО: Интерфейс приложений на основе WebView не является нативным, а только делается похожим на него с помощью HTML/CSS-стилей


При разработке приложений на PhoneGap требуется опыт HTML, JavaScript, CSS, а также Objective C, Java и хорошие инженерные знания для интеграции нативной и кроссплатформенной частей. Пользовательский интерфейс организован по принципу одностраничного HTML - в реальных приложениях со сложным интерфейсом будут подергивания и подтормаживания (особенности мобильных WebView, которые еще и могут отличаться у разных производителей). Для передачи данных через мост их необходимо сериализовать/десериализовать в Json. В целом, мост используется редко, так как вся жизнь приложения проходит внутри WebView.


ВАЖНО: Для передачи сложных структур данных и классов между нативной частью и WebView их необходимо сериализовать/десериализовать в формате JSON


Напоследок отметим, что PhoneGap уже достаточно зрелое решение с большим количеством готовых плагинов.

************

Итак, PhoneGap можно рекомендовать для быстрой разработки простых приложений (до 15 экранов) с небольшой пользовательской аудиторией (например, решение внутри компании) или прототипов.

3.2 ReactNative

Одним из интересных решений в области кроссплатформенной разработки мобильных приложений является ReactNative, созданный в Facebook. Этот фреймворк дает возможность использовать JavaScript для описания нативного интерфейса и логики работы приложений. Сам по себе JS-движок обеспечивает производительность, сопоставимую с нативной. Однако не стоит забывать, что и в архитектуре ReactNative присутствует мост, снижающий скорость работы с платформенной функциональностью и UI.

Как видим, проект состоит из нативной части на Objective C, Java или C#, которая инициализирует JS-код и взаимодействует с операционной системой. Далее JS-приложение берет управление в свои руки и при помощи ReactNative начинает создавать нативные объекты и управлять ими из JavaScript. Стоит добавить, что архитектура ReactNative позволяет осуществлять обновление JS-кода без перезапуска приложения (hot reloading). Это допускает обновление кроссплатформенной части без необходимости перепубликации приложений в AppStore и Google Play. Также можно использовать библиотеки из Npm и большое количество сторонних плагинов.

Необходимо учитывать, что из-за ограничений iOS (нет возможности реализовать JIT) код JavaScript на лету интерпретируется, а не компилируется. В целом это не сильно сказывается на производительности в реальных приложениях, но помнить об этом стоит.


ВАЖНО: Для передачи сложных структур данных и классов между нативной частью и JS-движком их необходимо сериализовать/десериализовать в формате JSON


При создании приложений на ReactNative требуется опыт JavaScript, а также хорошие знание iOS и Android. Интеграцию нативной и кроссплатформенной частей легко сделать по официальной документации. Пользовательский интерфейс является полностью нативным, но имеет ограничения и особенности при стилизации из JS-кода, к которым придется привыкнуть. Для передачи данных через мост их необходимо сериализовать/десериализовать в Json. Плюс мост используется для управления нативными объектами, что также может вести к падению производительности при неэффективном использовании (например, часто менять свойства нативных UI-объектов из JS-кода при анимациях в ручном режиме).

Также следует учитывать юность фреймворка - имеются узкие места или ошибки, о которых узнаешь только во время разработки. И практически всегда требуется реализация нативной части на Objective C и Java.

************

Итак, ReactNative можно рекомендовать для быстрой разработки приложений средней сложности (до 40 экранов), в команде должны быть не только опытные JS-разработчики, но и хорошие специалисты по iOS (ObjC/Swift) и Android (Java/Kotlin).

3.3 Qt

Qt является одним из старейших кроссплатформенных фреймворков и используется очень широко для разработки embedded и десктопных приложений. Архитектура Qt позволяет портировать его в те операционные системы, которые имеют API для C++. И iOS, и Android (NDK), и Windows такой возможностью обладают, хотя и все со своими особенностями.

Один из главных плюсов Qt - собственная эффективная система отрисовки пользовательского интерфейса либо на базе растрового движка (например, CoreGraphics в iOS), либо на базе Open GL (ES). Именно это и делает фреймворк портируемым. То есть в Qt используются свои механизмы отрисовки UI - приложение будет выглядеть нативным настолько, насколько вы его сами стилизуете.

Как видим, на iOS используются стандартные модули CoreGraphics и UIKit для отрисовки пользовательского интерфейса. В Android ситуация чуть посложнее, так как Qt использует механизмы NDK для отрисовки UI, а для доступа к Java API и управления приложением используется уже знакомый нам мост JNI. Также в iOS и Android может использоваться Open GL ES для отрисовки QML или работы с 3D.

В Windows имеется прямой доступ к C++ API и все работало бы отлично, если бы не необходимость использовать конвертацию вызовов Open GL ES в вызовы DirectX (растровая отрисовка не удовлетворяет по производительности, а Open GL ES нет в Windows UWP). В этом помогает библиотека ANGLE.


ВАЖНО: Интерфейс приложений на основе Qt не является нативным, а только делается похожим на него с помощью стилизации


В целом Qt можно было бы рекомендовать как вещь в себе - только готовые модули самого фреймворка плюс платформонезависимые библиотеки на C++. Но в реальных проектах его использовать будет очень непросто - неродной UI, отсутствуют сторонние компоненты (только библиотеки “из коробки”), возникают сложности при сборке и отладке приложения, а также при доступе к нативной функциональности. Из плюсов - высокая производительность кода на C++.

************

Итак, Qt можно рекомендовать для разработки приложений под iOS, Android и Windows UWP только в том случае, если у вас уже имеются большой опыт работы с Qt и понимание непростых системных механизмов. Стоит учитывать, что интерфейс в любом случае может быть только похожим на родной.

3.4 Xamarin

Xamarin сейчас доступен в open source и появился в качестве развития проекта Mono (http://www.mono-project.com), открытой реализации инфраструктуры .NET для Unix-систем. Изначально Mono поддерживался компанией Novell и позволял запускать .NET-приложения в Linux и других открытых ОС.

Для взаимодействия с родными (для C) интерфейсами операционных систем в Mono используется механизм P/Invoke (http://www.mono-project.com/docs/advanced/pinvoke/). На основе Mono были созданы фреймворки MonoTouch и MonoDroid, которые затем переименовали в Xamarin.iOS и Xamarin.Android, и теперь вместе называют “классическим Xamarin” (Xamarin Classic).

Классический Xamarin предоставляет полный доступ к нативным API, то есть можно создавать нативные приложения iOS/Android с помощью C# без единой строчки на Objective C и Java. Нативные библиотеки подключаются через механизм байндинга (Native Library Binding). Взаимодействие с ОС происходит через мост и механизм оберток (wrappers), однако нет необходимости сериализовать данные, так как осуществляется автоматический маршалинг и есть возможность прямой передачи ссылок между средами Mono Managed и Native. Можно также использовать большое количество .NET-библиотек из NuGet.

Инфраструктура .NET/Mono предполагает использование JIT по аналогии с Java, когда приложение компилируется в промежуточный байт-код и уже потом интерпретируется во время исполнения. Но из-за ограничений iOS нет возможности использовать JIT, и поэтому байт-код Xamarin.iOS-приложений компилируется в нативный бинарный и статически линкуется вместе с библиотеками. Такая компиляция называется AOT (Ahead Of Time) и является обязательной в Xamarin.iOS. В Xamarin.Android же помимо AOT доступен и режим JIT, когда виртуальное окружение Mono работает параллельно с Dalvki/ART и интерпретирует код во время исполнения.

Как видим, общая база кода между платформами ограничивается бизнес-логикой и механизмами работы с данными. К сожалению, UI и платформенную функциональность приходится реализовывать отдельно для каждой платформы. В результате шарить можно не более 30%-40% от общей базы кода мобильных приложений. Для достижения большего результата необходимо использовать Xamarin.Forms, о котором мы расскажем в Главе 3.5.

Ключевым преимуществом классического Xamarin является использование языка C# для всего кода и, как следствие, разработчиков, которые уже хорошо знакомы с .NET. Также обязательным является хорошее знание и понимание механизмов iOS/Android, их классовых моделей, архитектур, жизненных циклов объектов и умение читать примеры на Objective C и Java.


ВАЖНО: Производительность C#-кода сопоставима с производительностью нативного кода в iOS/Android, но при взаимодействии с ОС используется мост, который может замедлять приложение при неэффективном использовании


Приложение на Xamarin.iOS/Xamarin.Android обычно состоит из shared (общей) части, которая упаковывается в .NET-библиотеку и платформенной части, которая имеет полный доступ к API, включая нативный пользовательский интерфейс. В платформенной части содержится описание экранов, ресурсы, стили, шрифты - практически 100% структура нативного проекта на Objective C или Java, только на C#. Также есть возможность подключать код на C# в нативных проектах с помощью Embeddinator-4000 (https://mono.github.io/Embeddinator-4000).

Классический Xamarin является зрелым решением и обеспечивает максимально близкий к нативному опыт разработки для C#-программистов и использованием привычных инструментов вроде Visual Studio.

************

Итак, если стоит задача реализовать полностью нативное приложение и при этом имеются опытные C#-разработчики, то Xamarin может стать хорошим выбором для широкого спектра задач, как больших (более 40), так и маленьких (до 10).

3.5 Xamarin.Forms

Если у вас стоит цель максимизировать общую базу кода, то классический Xamarin здесь явно проигрывает всем остальным фреймворкам (PhoneGap, ReactNative, Qt и их аналогам). Это понимали и в самом Xamarin, поэтому выпустили решение, позволяющее использовать единое описание UI и простые механизмы доступа к платформенным фичам - Xamarin.Forms.

Библиотека Xamarin.Forms работает поверх описанного ранее классического Xamarin и фактически предоставляет механизмы виртуализации пользовательского интерфейса и дополнительную инфраструктуру.

Xamarin.Forms (XF) решает своего рода задачу «последней мили», предоставляя единый API для работы с пользовательским интерфейсом в разных операционных системах (iOS, Android, Windows UWP/WPF, Linux Gtk#, Mac OS X, Tizen). При этом сам интерфейс остается полностью родным.

Для того, чтобы лучше понять, как работает XF, давайте рассмотрим простую кнопку. Одним из базовых механизмов являются рендереры (renderers), благодаря которым при отображении кнопки Xamarin.Forms фактически на экран добавляется нативный контрол, а свойства XF-кнопки динамически пробрасываются в свойства нативной кнопки на каждой платформе. В ReactNative используются похожие механизмы.

Общая (shared) часть на Xamarin.Forms обычно реализуется в виде библиотеки (Portable/PCL или .NET Standard) и имеет доступ к базе компонентов в NuGet. Платформенная часть реализуется на базе Xamarin Classic и имеет полный доступ к API, а также возможность подключения сторонних библиотек. При этом общий процент кода между платформами обычно доходит до 85%. Также Xamarin.Forms можно использовать в режиме Embedded для создания отдельных экранов и View внутри приложений на классическом Xamarin.iOS и Xamarin.Android.

Если вам будем достаточно уже доступных в Xamarin.Forms компонентов и плагинов, то не потребуется глубоких знаний в iOS/Android/Windows. Однако для более сложных сценариев (свои контролы, полная реализация дизайна в режиме pixel perfect) все же потребуется хорошее знание ОС и ее механизмов, плюс понимание Xamarin.Forms.

Несмотря на то, что классический Xamarin является зрелым и стабильным решение, Xamarin.Forms еще достаточно молодая и активно развивающаяся над ним надстройка, поэтому могут проявляться проблемы и узкие места, с которыми стоит быть внимательным.

************

Итак, Xamarin.Forms можно рекомендовать для быстрой разработки прототипов на C#, однако Xamarin.Forms также можно использовать для корпоративных и бизнес-приложений любого масштаба (100 и более экранов). Внешний вид, производительность и поведение приложений будет полностью нативным, но стоит не забывать об эффективном взаимодействии с операционной системой через мост.

Заключение

В нашем руководстве мы рассмотрели особенности популярных мобильных фреймворков с точки зрения архитектуры. Сами по себе кроссплатформенные приложения являются очень быстрыми и сопоставимы с нативными, однако необходимость использования моста немного снижает скорость при взаимодействии с родными API.

Общий вывод: во всех популярных кроссплатформенных фреймворках используется мост, снижающий скорость взаимодействия с нативной частью. Следует оптимизировать узкие места (специфичные для каждого фреймворка) при создании пользовательского интерфейса. Финальный выбор будет зависеть от имеющихся в команде компетенций и требований к конечному результату.

При выборе фреймворка стоит учитывать не только язык программирования, но и необходимый уровень знаний целевых операционных систем (iOS, Android, Windows), а также опираться на опыт вашей команды разработчиков. Например, при использовании PhoneGap можно обойтись поверхностными знаниями ОС, если не требуется вручную реализовать платформенную функциональность. А для Xamarin Classic придется стать экспертом в iOS и/или Android.

В качестве итога давайте соберем все рекомендации по выбору фреймворков в одном месте:

  • PhoneGap - если вам необходимо быстро сделать простое приложение или прототип и в команде есть опыт разработки одностраничных веб-приложений (HTML, JavaScript, CSS). В большинстве случаев можно обойтись готовыми плагинами для нативной функциональности. Из минусов - неродной интерфейс с частыми подергиваниями и залипаниями и непростой доступ к нативной части. Процент разделяемого кода - до 95%.

  • ReactNative - отлично подойдет для опытных JavaScript-разработчков и команд, но потребует достаточно хорошего знания iOS Objective C API и Android Java API. Приложения выглядят и работают нативно, но стоит учитывать юность фреймворка. Процент разделяемого кода - до 90%.

  • Xamarin Classic - если у вас есть опытные C#-разработчики, то им потребуется глубоко освоить iOS и Android. Приложения будут полностью нативными, хотя и написаны на C#. Объем общей базы кода в редких случаях превышает 40%.

  • Xamarin.Forms - подойдет опытным C#-разработчикам, особенно со знанием XAML. Для приложений с простым интерфейсом (стандартные контролы) не потребуется глубоких знаний iOS/Android/Windows. Процент разделяемого кода - до 90%.

  • Qt - этот фреймворк можно рекомендовать только в случае, если у вас уже есть существующее приложение (например, embedded) и его необходимо запустить на iOS/Android. Высокие требования к квалификации разработчиков, непростой доступ к нативной функциональности и неродной UI являются заметными минусами фреймворка. Процент разделяемого кода может доходить до 95%.


Черников Вячеслав, [email protected]

Наши контакты: binwell.com, +7 (499) 677-49-27, [email protected]

Вы также можете подписаться на наш Medium, где мы часто выкладываем интересные материалы по кроссплатформенной разработке мобильных приложений на Xamarin, Xamarin.Forms, архитектурам и технологиям разработки, а также Mobile DevOps: medium.com/binwell