Как написать кроссплатформенное приложение

Рынку мобильных приложений уже больше десяти лет, однако он до сих пор бурно развивается. Спрос на создание мобильных приложений со стороны компаний постоянно растёт и он всё ещё заметно превышает предложение, что приводит к постоянному удорожанию разработки. Одно из решений в удешевлении этого процесса — кроссплатформенная разработка, когда один и тот же программный код используется на всех платформах.

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

Давайте для начала пройдемся ещё раз по терминологии.

Родные

Если разработчики в процессе написания приложения пользуются принятым для конкретной платформы языком программирования, будь то Objective-C и Swift для iOS или Java или Kotlin для Android, такое приложение будет называться нативным (от англ. native — родной, естественный).

Преимущества нативных приложений:

  • скорость работы и отклика интерфейса. Приложение реагирует на нажатия мгновенно, практически отсутствуют задержки в анимации, скроллировании, получении и выводе данных;
  • понятный и простой доступ к функциям и датчикам устройства. Для разработчика не представляет проблемы работа с геолокацией, пуш-уведомлениями, съёмкой фото и видео через камеру, звуком, акселерометром и другими датчиками;
  • возможность углублённой работы с функциями смартфона. Как и в предыдущем пункте, такие вещи, как анимации, создание сложных интерфейсов и работа нейросетей прямо на устройствах реализуются, может быть, и не просто, но прогнозируемо;
  • родной для платформы интерфейс. Нативные приложения обычно оперируют «платформенными» элементами интерфейса: меню, навигация, формы и все остальные элементы дизайна берутся от операционной системы и потому привычны и понятны пользователю.

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

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

На чём писать кроссплатформенные приложения

И не родные

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

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

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

Предполагается, что большая часть такого кода может переносится между платформами — очевидно, что, например, логика совершения покупок, сохранения товара в корзину, просчёта маршрута для такси, написания сообщения в мессенджер не меняется в зависимости о того, Android у клиента или iOS. Нужно лишь доработать UI и UX для платформ, но сейчас, в определённых пределах, даже это можно объединить — например, меню-гамбургер активно используется как на Android, так и на iOS. Так что даже внесений исправления в интерфейс для того, чтобы приложение отвечало духу и букве нужной платформы — вопрос желания, необходимой скорости и качества разработки.

Преимущества:

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

Недостатки:

  • неродной интерфейс или, как минимум, необходимость работы с интерфейсом каждой платформы отдельно. У каждой системы свои требования к дизайну элементов и иногда они взаимоисключающи. При разработке это необходимо учитывать;
  • проблемы в реализации сложных функций или возможные проблемы работы даже с простыми процедурами в силу ошибок самих фреймворков разработки. Кроссплатформенная среда лишь транслирует запросы к системным вызовам и интерфейсам в понимаемый ею, системой, формат, и потому на этом этапе возможны как сложности с пониманием, так и возникновение ошибок внутри самого фреймворка;
  • скорость работы. Так как кроссплатформенная среда является «надстройкой» над кодом (не всегда, но в определённых ситуациях), в ней возникают свои задержки и паузы в отработке действий пользователя и выводе на экран результатов. Это было особенно заметно несколько лет назад на смартфонах, более маломощных относительно сегодняшних, однако сейчас, с ростом производительности мобильных устройств, этим уже можно пренебречь.

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

Популярные платформы и инструменты кроссплатформенной мобильной разработки

Как мы написали выше, есть два подхода — превращение кода в нативный на этапе сборки или добавление определённой обёртки, транслирующей вызовы к системе и от неё.

Cordova и PWA — два инструмента, работающие как раз в идеологии обёртки.

Cordova и PWA

Cordova и HTML5

Одно из самых популярных направлений в кроссплатформенном программировании, которое часто по-народному называют PhoneGap. Фактически создаётся мобильный сайт, который «оборачивается» небольшим платформенным кодом, транслирующим вызовы от системы к приложению и обратно.

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

Для такого подхода создано огромное количество фреймворков, но все они делают фактически одно и тоже. Различие между ними в том, что Cordova (PhoneGap) не задаёт ограничений и шаблонов на логику и UI для вашего HTML5-проекта, а фреймворки оперируют собственными готовыми UI-элементами, имитирующими мобильные платформы, и своей логикой разработки. В качестве примера такого подхода можно указать: Ionic Framework — обёртка; Framework7, Mobile Angular UI, Sencha Touch, Kendo UI — интерфейсные фреймворки.

PWA

Модная технология от Google — это те же самые веб-приложения, но за счёт использования определённых технологий (в первую очередь это так называемые Service Worker — работающие в фоновом режиме скрипты, и Web App Manifest — описание веб-приложения в понятном для мобильной системы виде) они без обёртки из PhoneGap могут работать как нативные. Они могут устанавливаться на домашний экран в обход магазина приложений, работать в офлайне, работать с пуш-уведомлениями, с нативными функциями.

Проблема в том, что не все платформы даже сейчас поддерживают эти «определённые технологии». В первую очередь это касается Apple, которой, видимо, очень не нравится возможность распространять приложения в обход App Store.

Учтя все недостатки HTML5-решений, многие компании создали инструменты, которые позволяют писать код на одном, не нативном, языке, а он потом транслируется в нативный. Так убивается два зайца одновременно: кодовая база получается одна, а приложения получаются максимально близки к нативному.

Xamarin, React Native и Flutter

Xamarin

Платформа компании Microsoft. Используется стандартный для Enterprise-разработки язык программирования С#, кроссплатформенная среда разработки — Visual Studio. На выходе — нативные приложения для iOS, Android и Windows. Правда, относительно большого размера.

React Native

Платформа от Facebook — приложения пишутся на JavaScript и с использованием CSS-подобных стилей. Интерфейс получается родной, а код интерпретируется уже на платформе, что придаёт ему нужную гибкость.

Будучи относительно молодой платформой, React Native пока очевидно (хоть и не катастрофически) страдает от недостатка средств разработки и документации.

Flutter

Естественно, не мог обойти тему кроссплатформенной разработки Android и iOS-приложеий и такой гигант, как Google. Flutter, пока, правда, существующий только в бета-версии, исповедует отличный от React Native и Xamarin подход. Он не превращает исходный код в нативный, который выполняется платформой, а на самом деле рисует окно на экране смартфона и отрисовывает все элементы сам. В качестве языка используется «фирменный» Dart, который Google создал как усовершенствованную версию JavaScript.

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

Платформа быстро развивается и Google вкладывает в это много сил и средств. Но по сравнению с Flutter даже React Native кажется вполне устоявшейся и впечатляющей экосистемой.

Что выбрать

У вас уже наверняка пошла голова кругом, а понимания что выбрать, так и не появилось. Давайте представим простой список вопросов, который вам поможет:

  • должно хоть как-то работать на любом устройстве? Выбирайте HTML как основу;
  • у вас достаточно средств, нет спешки и вы хотите самое качественное приложение?
    Вам прямой путь в нативную разработку;
  • у вас есть «встроенный» веб-разработчик или вы просто хотите быстро и просто попробовать мобильное приложение в деле?
    Тут можно рекомендовать Cordova/HTML или PWA;
  • у вас есть собственная CRM-система и поддерживающий ее C#-разработчик? Берите Xamarin;
  • вы «хотите попробовать», но надо сделать всё красиво и модно?
    Смотрите в сторону React Native или Flutter.

Можно зайти и с другой стороны. Посмотрите на функциональность, которая вам потребуется в приложении, и исходите из этого:

  • простое приложение-визитка?
    Возьмите React Native или HTML5 и вы получите две платформы за минимальную цену;
  • у вас есть сайт с большой посещаемостью и вам нужно протестировать гипотезу присутствия в мобильном пространстве?
    HTML5;
  • сложные приложения с доступом к нужным функциям устройств?
    Нативная разработка, Xamarin, React Native.

Какой инструмент выбрать для кроссплатформенной разработки

Кроссплатформенная разработка — не панацея

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

У вас остались сомнения и вопросы о кроссплатформенных приложениях? Почитайте о том, как мы создавали приложение ClassBoom для быстрого получения абонемента в одно из спортивных заведений города и попробуйте приложение ВсеПлатежи для оплаты всевозможных видов услуг — от ЖКХ до заказов в интернет-магазинах. А лучше запишитесь на бесплатную консультацию, заполнив форму с указанием примерного бюджета и кратким описанием идеи или свяжитесь с нашим менеджером Катей по телефону +7 495 204-35-03.

В честь запуска в «Практикуме» курсов по мобильной разработке для Android и для iOS мы разбираем эту тему в журнале: 

  • Какую платформу выбрать — iOS или Android.
  • Кроссплатформенная разработка ← вы здесь.
  • Пробный кроссплатформенный проект.
  • Пробные нативные проекты для Android и iOS (с божьей помощью).

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

Но что, если разрабатывать сразу для обеих платформ? Реально ли это и нужно ли? Вот об этом поговорим.

Что такое кроссплатформенная разработка

Кроссплатформенная разработка — это когда мы один раз пишем универсальный код, который потом превращается в приложение и на iOS, и на Android. Реализуется это так:

  1. Один раз пишем кроссплатформенный код.
  2. При компиляции выбираем, для какой платформы адаптировать код.
  3. Кроссплатформенный фреймворк сам меняет свои команды на те, которые приняты на выбранной платформе.
  4. Итоговый код пригоден для запуска на выбранной платформе. 

Можно поставить сразу две галочки и скомпилировать код сразу под iOS и Android — в этом случае фреймворк по очереди преобразует универсальные команды в нужный код и мы получим сразу два приложения. 

В мобильной разработке есть два кроссплатформенных фреймворка — React Native и Flutter. Они написаны на разных языках и работают по-разному.

Мобильная разработка сразу для iOS и Android: это как? 

React Native — JavaScript на максималках

React Native — это развитие библиотеки React, которую используют для создания веб-интерфейсов. Сначала React Native использовали для iOS-приложений, но быстро сообразили, что из него можно сделать универсальный инструмент, и добавили поддержку Android. 

Когда код на React Native компилируется под конкретную платформу, все команды на JavaScript преобразуются во внутренние инструкции операционной системы. За это отвечает движок JavaScriptCore — его использует мобильный браузер Safari. 

Если вы знаете JavaScript, то легко разберётесь в коде на React Native. Вот простой хеллоу ворлд:

var styles = React.StyleSheet.create({
  text: {
    color: 'black',
    backgroundColor: 'white',
    fontSize: 30,
    margin: 80
  }
});
class PropertyFinderApp extends React.Component {
  render() {
    return React.createElement(React.Text, {style: styles.text}, "Hello World!");
  }
}

На React Native написано много известного:

  • Skype,
  • Uber,
  • SoundCloud,
  • Pinterest,
  • Discord.

Сейчас React Native становится всё более популярным: у него большое сообщество, понятная документация и растущий спрос на разработчиков.

Flutter — производительность на своём языке

Если для React Native достаточно знаний JavaScript, то для Flutter нужно будет изучить новый язык — Dart. Его придумала компания Google во имя быстродействия приложений. 

Главное преимущество Flutter в том, что ему не нужна прослойка в виде JavaScriptCore — компилятор переводит всё сразу в код для конкретной платформы. 

Типичный код на Flutter более сложный, чем React Native. Вот пример:

class  _MyHomePageState  extends  State<MyHomePage> {  
  String _name = "";  
  bool _isLoading = false;  

  @override  
  Widget build(BuildContext context) => Center(  
    child: new Column(  
      mainAxisAlignment: MainAxisAlignment.center,  
      children: <Widget>[  
        Padding(  
          padding: EdgeInsets.all(16.0),  
          child: Text(  
            '$_name',  
          ),  
        ),  
        LoadingButton(  
          isLoading: _isLoading,  
          action: _generateName,  
        )  
      ],  
    ),  
  );  
}

На Flutter написано много приложений компании Google (например, почтовый клиент Gmail), а ещё:

  • приложение магазина Aliexpress,
  • Square,
  • Ebay,
  • Groupon.

Плюсы и минусы кроссплатформенной разработки

Плюсы очевидны — такая разработка позволяет сэкономить много времени и сил:

✅ Приложение выходит сразу для iOS и Android.

✅ На написание кода сразу для двух платформ требуется меньше времени.

✅ Не нужно думать, как запрограммировать стандартные элементы интерфейса — с этим справится фреймворк.

✅ При обновлении новую версию получают сразу обе платформы.

✅ Пользователи получают одинаковый интерфейс и логику работы.

Но в конкретном проекте минусы иногда могут оказаться сильнее преимуществ:

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

❌ У программиста должна быть высокая квалификация — он должен знать особенности разработки для iOS и Android.

❌ Когда приложение становится слишком большим и обрастает новыми возможностями, его становится сложно поддерживать.

Хак: приложения Webview

Есть ещё один вариант кроссплатформенной разработки — создавать приложения с опорой на Web View, то есть на вывод веб-страниц внутри приложения.

В приложениях Webview есть нативная «обёртка» — например нижнее меню — и экран загрузки. Но в сердце этого нативного приложения — большое пустое окно браузера, которое ведёт себя ровно как браузер, с теми же технологиями, ограничениями и безопасностью. 

Когда приложение запускается, оно загружает в этом браузере какой-то сайт — например, если это сервис по заказу суши, он загружает онлайн-меню своего ресторана. Это меню по сути является сайтом — с HTML, JavaScript, каким-то бэкендом, куками и прочими веб-штуками.

⚠️ Главные минусы приложений с Web View — зависимость от интернета и ненативный интерфейс. Все кнопки, выпадайки и галочки нужно программировать с нуля и тестировать на множестве устройств; а если у пользователя проблемы с интернетом, то вообще ничего не будет работать.

Вот винтажный мемчик про это:

Мобильная разработка сразу для iOS и Android: это как?

Что дальше

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

Вёрстка:

Кирилл Климентьев

Время на прочтение
13 мин

Количество просмотров 22K

Reactive MVVM and .NET Standard

Сегодня платформа .NET является по-настоящему универсальным инструментом – с её помощью можно решать широчайший круг задач, включая разработку прикладных приложений для популярных операционных систем, таких, как Windows, Linux, MacOS, Android и iOS. В настоящей статье рассмотрим архитектуру кроссплатформенных .NET приложений с использованием шаблона проектирования MVVM и реактивного программирования. Познакомимся с библиотеками ReactiveUI и Fody, научимся реализовывать интерфейс INotifyPropertyChanged с помощью атрибутов, затронем основы AvaloniaUI, Xamarin Forms, Universal Windows Platform, Windows Presentation Foundation и .NET Standard, изучим эффективные инструменты для модульного тестирования слоёв модели и модели представления приложения.

Материал является адаптацией статей «Reactive MVVM For The .NET Platform» и «Cross-Platform .NET Apps Via Reactive MVVM Approach», опубликованных автором ранее на ресурсе Medium. Примеры кода доступны на GitHub.

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

При разработке кроссплатформенных приложений на платформе .NET необходимо писать переносимый и поддерживаемый код. В случае работы с фреймворками, использующими диалекты XAML, такими, как UWP, WPF, Xamarin Forms и AvaloniaUI, этого можно достичь с помощью шаблона проектирования MVVM, реактивного программирования и стратегии разделения кода .NET Standard. Данный подход улучшает переносимость приложений, позволяя разработчикам использовать общую кодовую базу и общие программные библиотеки на различных операционных системах.

Подробнее рассмотрим каждый из слоёв приложения, построенного на основе архитектуры MVVM – модель (Model), представление (View) и модель представления (ViewModel). Слой модели представляет собой доменные сервисы, объекты передачи данных, сущности баз данных, репозитории – всю бизнес-логику нашей программы. Представление отвечает за отображение элементов пользовательского интерфейса на экран и зависит от конкретной операционной системы, а модель представления позволяет двум описанным выше слоям взаимодействовать, адаптируя слой модели для взаимодействия с пользователем – человеком.

Архитектура MVVM предполагает разделение ответственности между тремя программными слоями приложения, поэтому эти слои могут быть вынесены в отдельные сборки, нацеленные на .NET Standard. Формальная спецификация .NET Standard позволяет разработчикам создавать переносимые библиотеки, которые могут использоваться в различных реализациях .NET, с помощью одного унифицированного набора API-интерфейсов. Строго следуя архитектуре MVVM и стратегии разделения кода .NET Standard, мы сможем использовать уже готовые слои модели и модели представления при разработке пользовательского интерфейса для различных платформ и операционных систем.

image

Если мы написали приложение для операционной системы Windows с помощью Windows Presentation Foundation, мы с лёгкостью сможем портировать его на другие фреймворки, такие, как, например, Avalonia UI или Xamarin Forms – и наше приложение будет работать на таких платформах, как iOS, Android, Linux, OSX, причём пользовательский интерфейс станет единственной вещью, которую нужно будет написать с нуля.

Традиционная реализация MVVM

Модели представления, как правило, включают в себя свойства и команды, к которым могут быть привязаны элементы разметки XAML. Для того, чтобы привязки данных заработали, модель представления должна реализовывать интерфейс INotifyPropertyChanged и публиковать событие PropertyChanged всякий раз, когда какие-либо свойства модели представления изменяются. Простейшая реализация может выглядеть следующим образом:

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel() => Clear = new Command(() => Name = string.Empty);
    
    public ICommand Clear { get; }
    
    public string Greeting => $"Hello, {Name}!";

    private string name = string.Empty;
    public string Name
    {
        get => name;
        set
        {
            if (name == value) return;
            name = value;
            OnPropertyChanged(nameof(Name));
            OnPropertyChanged(nameof(Greeting));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

XAML, описывающий UI приложения:

<StackPanel>
    <TextBox Text="{Binding Name, Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding Greeting, Mode=OneWay}"/> 
    <Button Content="Clear" Command="{Binding Clear}"/>
</StackPanel>

И это работает! Когда пользователь вводит своё имя в текстовое поле, текст ниже мгновенно меняется, приветствуя пользователя.

MVVM binding sample

Но постойте! Нашему UI нужны всего два синхронизированных свойства и одна команда, почему мы должны написать более двадцати строк кода, чтобы наше приложение заработало корректно? Что случится, если мы решим добавить больше свойств, отражающих состояние нашей модели представления? Кода станет больше, код станет запутаннее и сложнее. А нам его ещё поддерживать!

Рецепт #1. Шаблон «Наблюдатель». Короткие геттеры и сеттеры. ReactiveUI

На самом деле, проблема многословной и запутанной реализации интерфейса INotifyPropertyChanged не нова, и существует несколько решений. Первым делом стоит обратить внимание на ReactiveUI. Это кроссплатформенный, функциональный, реактивный MVVM фреймворк, позволяющий .NET разработчикам использовать реактивные расширения при разработке моделей представления.

Реактивные расширения являются реализацией шаблона проектирования «Наблюдатель», определяемого интерфейсами стандартной библиотеки .NET – «IObserver» и «IObservable». Библиотека также включает в себя более пятидесяти операторов, позволяющих преобразовывать потоки событий – фильтровать, объединять, группировать их – с помощью синтаксиса, похожего на язык структурированных запросов LINQ. Подробнее о реактивных расширениях можно почитать здесь. ReactiveUI также предоставляет базовый класс, реализующий INotifyPropertyChanged – ReactiveObject. Давайте перепишем наш образец кода, используя предоставленные фреймворком возможности.

public class ReactiveViewModel : ReactiveObject
{
    public ReactiveViewModel()
    {
        Clear = ReactiveCommand.Create(() => Name = string.Empty);
        this.WhenAnyValue(x => x.Name) 
            .Select(name => $"Hello, {name}!")
            .ToProperty(this, x => x.Greeting, out greeting);
    }

    public ReactiveCommand Clear { get; }

    private ObservableAsPropertyHelper<string> greeting;
    public string Greeting => greeting.Value;

    private string name = string.Empty;
    public string Name
    {
        get => name;
        set => this.RaiseAndSetIfChanged(ref name, value);
    }
}

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

Рецепт #2. Инкапсуляция INotifyPropertyChanged. ReactiveProperty

Альтернативным решением может стать использование библиотеки ReactiveProperty, предоставляющей классы-обёртки, ответственные за отправку уведомлений пользовательскому интерфейсу. С ReactiveProperty модель представления не должна реализовывать каких-либо интерфейсов, вместо этого, каждое свойство реализует INotifyPropertyChanged само. Такие реактивные свойства также реализуют IObservable, а это значит, что мы можем подписываться на их изменения, как если бы мы использовали ReactiveUI. Изменим нашу модель представления, используя ReactiveProperty.

public class ReactivePropertyViewModel
{
    public ReadOnlyReactiveProperty<string> Greeting { get; }
    public ReactiveProperty<string> Name { get; }
    public ReactiveCommand Clear { get; }

    public ReactivePropertyViewModel()
    {
        Clear = new ReactiveCommand();
        Name = new ReactiveProperty<string>(string.Empty);
        Clear.Subscribe(() => Name.Value = string.Empty);
        Greeting = Name
            .Select(name => $"Hello, {name}!")
            .ToReadOnlyReactiveProperty();
    }
}

Нам всего лишь нужно объявить и инициализировать реактивные свойства и описать связи между ними. Никакого шаблонного кода писать не нужно, не считая инициализаторов свойств. Но у этого подхода есть недостаток – мы должны изменить наш XAML, чтобы привязки данных заработали. Реактивные свойства являются обёртками, поэтому UI должен быть привязан к собственному свойству каждой такой обёртки!

<StackPanel>
    <TextBox Text="{Binding Name.Value, Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding Greeting.Value, Mode=OneWay}"/> 
    <Button Content="Clear" Command="{Binding Clear}"/>
</StackPanel>

Рецепт #3. Изменение сборки во время компиляции. PropertyChanged.Fody + ReactiveUI

В типичной модели представления каждое публичное свойство должно уметь отправлять уведомления пользовательскому интерфейсу, когда его значение изменяется. С пакетом PropertyChanged.Fody волноваться об этом не придётся. Единственное, что требуется от разработчика – пометить класс модели представления атрибутом AddINotifyPropertyChangedInterface – и код, ответственный за публикацию события PropertyChanged, будет дописан в сеттеры автоматически после сборки проекта, вместе с реализацией интерфейса INotifyPropertyChanged, если таковая отсутствует. В случае необходимости превратить наши свойства в потоки изменяющихся значений, мы всегда сможем использовать метод расширения WhenAnyValue из библиотеки ReactiveUI. Давайте перепишем наш образец в третий раз, и увидим, насколько лаконичнее станет наша модель представления!

[AddINotifyPropertyChangedInterface]
public class FodyReactiveViewModel
{
    public ReactiveCommand Clear { get; }
    public string Greeting { get; private set; }
    public string Name { get; set; } = string.Empty;

    public FodyReactiveViewModel()
    { 
        Clear = ReactiveCommand.Create(() => Name = string.Empty);
        this.WhenAnyValue(x => x.Name)
            .Select(name => $"Hello, {name}!")
            .Subscribe(x => Greeting = x);
    }
}

Fody изменяет IL-код проекта во время компиляции. Дополнение PropertyChanged.Fody ищет все классы, помеченные атрибутом AddINotifyPropertyChangedInterface или реализующие интерфейс INotifyPropertyChanged, и редактирует сеттеры таких классов. Подробнее о том, как работает кодогенерация и какие ещё задачи она позволяет решать, можно узнать из доклада Андрея Курoша «Reflection.Emit. Практика использования». Хотя PropertyChanged.Fody и позволяет нам писать чистый и выразительный код, устаревшие версии .NET Framework, включая 4.5.1 и старше, более не поддерживаются. Это означает, что вы, на самом деле, можете попробовать использовать ReactiveUI и Fody в своём проекте, но на свой страх и риск, и учитывая, что все найденные ошибки никогда не будут исправлены! Версии для .NET Core поддерживаются согласно политике поддержки Microsoft.

Рецепт #4. Изменение сборки во время компиляции. ReactiveUI.Fody

Ещё одним способом реализации шаблона MVVM при помощи кодогенерации и реактивного программирования является использование средств пакета ReactiveUI.Fody. Данный способ во многом схож с рецептом #3, однако здесь необходимо явно промаркировать все необходимые свойства, в которые необходимо внедрить INotifyPropertyChanged во время компиляции. Дополнительно, данный подход позволяет генерировать вычисляемые свойства только для чтения, использующие внутри класс ObservableAsPropertyHelper.

public class ReactiveFodyViewModel : ReactiveObject
{
    public ReactiveCommand<Unit, Unit> Clear { get; }

    [ObservableAsProperty] 
    public string Greeting { get; }
    
    [Reactive]
    public string Name { get; set; } = string.Empty;

    public ReactiveFodyViewModel()
    { 
        Clear = ReactiveCommand.Create(() => { Name = string.Empty; });
        this.WhenAnyValue(x => x.Name)
            .Select(name => $"Hello, {name}!")
            .ToPropertyEx(this, x => x.Greeting);
    }
}

Oт теории к практике. Валидация форм с ReactiveUI и PropertyChanged.Fody

Теперь мы готовы написать нашу первую реактивную модель представления. Давайте вообразим, будто мы разрабатываем сложную многопользовательскую систему, при этом думаем об UX и хотим собрать отзывы от наших клиентов. Когда пользователь отправляет нам сообщение, мы должны знать, является ли оно баг-репортом или предложением по улучшению системы, также мы хотим группировать отзывы по категориям. Пользователи не должны отправлять письма, пока не заполнят всю необходимую информацию корректно. Модель представления, удовлетворяющая перечисленным выше условиям, может выглядеть следующим образом:

[AddINotifyPropertyChangedInterface]
public sealed class FeedbackViewModel
{
    public ReactiveCommand<Unit, Unit> Submit { get; }
    public bool HasErrors { get; private set; }

    public string Title { get; set; } = string.Empty;
    public int TitleLength => Title.Length;
    public int TitleLengthMax => 15;

    public string Message { get; set; } = string.Empty;
    public int MessageLength => Message.Length;
    public int MessageLengthMax => 30;

    public int Section { get; set; }
    public bool Issue { get; set; }
    public bool Idea { get; set; }

    public FeedbackViewModel(IService service)
    {
        this.WhenAnyValue(x => x.Idea)
            .Where(selected => selected)
            .Subscribe(x => Issue = false);
        this.WhenAnyValue(x => x.Issue)
            .Where(selected => selected)
            .Subscribe(x => Idea = false);

        var valid = this.WhenAnyValue(
            x => x.Title, x => x.Message,
            x => x.Issue, x => x.Idea,
            x => x.Section, 
            (title, message, issue, idea, section) =>
                !string.IsNullOrWhiteSpace(message) &&
                !string.IsNullOrWhiteSpace(title) &&
                (idea || issue) && section >= 0);

        valid.Subscribe(x => HasErrors = !x);
        Submit = ReactiveCommand.Create(
            () => service.Send(Title, Message), valid
        );
    } 
}

Мы маркируем нашу модель представления с помощью атрибута AddINotifyPropertyChangedInterface – таким образом, все свойства будут оповещать UI об изменении их значений. С помощью метода WhenAnyValue, мы подпишемся на изменения этих свойств и будем обновлять другие свойства. Команда, ответственная за отправку формы, будет оставаться выключенной, пока пользователь не заполнит форму корректно. Сохраним наш код в библиотеку классов, нацеленную на .NET Standard, и перейдём к тестированию.

Модульное тестирование моделей представления

Тестирование – это важная часть процесса разработки программного обеспечения. С тестами мы сможем доверять нашему коду и перестать бояться его рефакторить – ведь для проверки корректности работы программы достаточно будет запустить тесты и убедиться в их успешном завершении. Приложение, использующее архитектуру MVVM, состоит из трёх слоёв, два из которых содержат платформонезависимую логику – и именно её мы сможем протестировать с помощью .NET Core и фреймворка XUnit. Для создания моков и стабов нам пригодится библиотека NSubstitute, предоставляющая удобный API для описания реакций на действия системы и значений, возвращаемых «поддельными объектами».

var sumService = Substitute.For<ISumService>();
sumService.Sum(2, 2).Returns(4);

Для улучшения читаемости как кода, так и сообщений об ошибках в наших тестах, используем библиотеку FluentAssertions. С ней нам не только не придётся запоминать, каким по счёту аргументом в Assert.Equal идёт фактическое значение, а каким – ожидаемое, но и код за нас будет писать наша IDE!

var fibs = fibService.GetFibs(10);
fibs.Should().NotBeEmpty("because we've requested ten fibs");
fibs.First().Should().Be(1);

Давайте напишем тест для нашей модели представления.

[Fact]
public void ShouldValidateFormAndSendFeedback()
{
    // Создадим экземпляр модели представления,
    // предоставим все необходимые зависимости.
    var service = Substitute.For<IService>();
    var feedback = new FeedbackViewModel(service);
    feedback.HasErrors.Should().BeTrue();

    // Имитируем пользовательский ввод.
    feedback.Message = "Message!";
    feedback.Title = "Title!";
    feedback.Section = 0;
    feedback.Idea = true;
    feedback.HasErrors.Should().BeFalse();
    
    // После вызова команды удостоверимся, 
    // что метод Send() объекта IService был 
    // вызван ровно один раз.
    feedback.Submit.Execute().Subscribe();
    service.Received(1).Send("Title!", "Message!");
}

UI для Универсальной платформы Windows

Хорошо, теперь наша модель представления протестирована и мы уверены, что всё работает, как ожидается. Процесс разработки слоя представления нашего приложения довольно прост – нам необходимо создать новый платформозависимый проект Universal Windows Platform и добавить в него ссылку на библиотеку .NET Standard, содержащую платформонезависимую логику нашего приложения. Далее дело за малым – объявить элементы управления в XAML, привязать их свойства к свойствам модели представления и не забыть указать контекст данных любым удобным способом. Сделаем это!

<StackPanel Width="300" VerticalAlignment="Center">
  <TextBlock Text="Feedback" Style="{StaticResource TitleTextBlockStyle}"/>
  <TextBox PlaceholderText="Title" 
           MaxLength="{Binding TitleLengthMax}" 
           Text="{Binding Title, Mode=TwoWay, 
                  UpdateSourceTrigger=PropertyChanged}"/>
  <TextBlock Style="{StaticResource CaptionTextBlockStyle}">
    <Run Text="{Binding TitleLength, Mode=OneWay}"/>
    <Run Text="letters used from"/>
    <Run Text="{Binding TitleLengthMax}"/>
  </TextBlock>
  <TextBox PlaceholderText="Message" 
           MaxLength="{Binding MessageLengthMax}"
           Text="{Binding Message, Mode=TwoWay, 
                  UpdateSourceTrigger=PropertyChanged}"/>
  <TextBlock Style="{StaticResource CaptionTextBlockStyle}">
    <Run Text="{Binding MessageLength, Mode=OneWay}"/>
    <Run Text="letters used from"/>
    <Run Text="{Binding MessageLengthMax}"/>
  </TextBlock>
  <ComboBox SelectedIndex="{Binding Section, Mode=TwoWay}">
    <ComboBoxItem Content="User Interface"/>
    <ComboBoxItem Content="Audio"/>
    <ComboBoxItem Content="Video"/>
    <ComboBoxItem Content="Voice"/>
  </ComboBox>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <CheckBox Grid.Column="0" Content="Idea" 
              IsChecked="{Binding Idea, Mode=TwoWay}"/>
    <CheckBox Grid.Column="1" Content="Issue" 
              IsChecked="{Binding Issue, Mode=TwoWay}"/>
  </Grid>
  <TextBlock Visibility="{Binding HasErrors}"
             Text="Please, fill in all the form fields." 
             Foreground="{ThemeResource AccentBrush}"/>
  <Button Content="Send Feedback" 
          Command="{Binding Submit}"/>
</StackPanel>

Наконец, наша форма готова.

uwp mvvm sample

UI для Xamarin.Forms

Чтобы приложение заработало на мобильных устройствах под управлением операционных систем Android и iOS, необходимо создать новый проект Xamarin.Forms и описать UI, используя элементы управления Xamarin, адаптированные для мобильных устройств.

xamarin.forms mvvm sample

UI для Avalonia

Avalonia – это кроссплатформенный фреймворк для .NET, использующий диалект XAML, привычный для разработчиков WPF, UWP или Xamarin.Forms. Avalonia поддерживает Windows, Linux и OSX и разрабатывается сообществом энтузиастов на GitHub. Для работы с ReactiveUI необходимо установить пакет Avalonia.ReactiveUI. Oпишем слой представления на Avalonia XAML!

avalonia mvvm sample

Заключение

Как мы видим, .NET в 2018 году позволяет нам писать по-настоящему кроссплатформенный софт – используя UWP, Xamarin.Forms, WPF и AvaloniaUI мы можем обеспечить поддержку нашим приложением операционных систем Android, iOS, Windows, Linux, OSX. Шаблон проектирования MVVM и такие библиотеки, как ReactiveUI и Fody, могут упростить и ускорить процесс разработки, позволяя писать понятный, поддерживаемый и переносимый код. Развитая инфраструктура, подробная документация и хорошая поддержка в редакторах кoда делают платформу .NET всё более привлекательной для разработчикoв программного обеспечения.

Если вы пишете настольные или мобильные приложения на .NET и ещё не знакомы с ReactiveUI, обязательно обратите на него внимание — фреймворк использует один из наиболее популярных клиентов GitHub для iOS, расширение Visual Studio для GitHub, git-клиент Atlassian SourceTree и Slack для Windows 10 Mobile. Цикл статей о ReactiveUI на Хабре может стать отличной точкой старта. Разработчикам на Xamarin наверняка пригодится курс «Building an iOS app with C#» от одного из авторов ReactiveUI. Об опыте разработки на AvaloniaUI можно узнать больше из статьи об Egram — альтернативном клиенте для Telegram на .NET Core.

Исходники кроссплатформенного приложения, описанного в статье и демонстрирующего возможности валидации форм с ReactiveUI и Fody, можно найти на GitHub. Пример кроссплатформенного приложения, работающего на Windows, Linux, macOS и Android, и демонстрирующего использование ReactiveUI, ReactiveUI.Fody и Akavache также доступен на GitHub.

#Руководства

  • 18 май 2020

  • 11

На C# можно создавать красивые приложения, но до недавних пор — не для всех платформ. Рассказываем, как писать одно приложение для всех ОС сразу.

 vlada_maestro / shutterstock

Евгений Кучерявый

Пишет о программировании, в свободное время создаёт игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Microsoft выпустила уже третью версию кросс-платформенного .NET Core с открытым исходным кодом, но мы до сих пор не получили инструмента для создания графических интерфейсов.

Пока есть Xamarin, который можно использовать только для Windows 10 и мобильных устройств. Но что делать тем, кто хочет создавать графические интерфейсы для Linux или Mac OS?

Тут помогут фреймворки от сторонних разработчиков.

Мне удалось найти два более-менее популярных фреймворка (оба основаны на Skia):

  1. SpaceVIL. Он привлёк меня тем, что в нём элементы GUI отрисовываются, а не берутся из API операционной системы. Поэтому приложение будет выглядеть одинаково на всех устройствах. В нём даже можно создавать собственные элементы любого вида. Однако он пока довольно сырой — об этом говорит уже то, что в официальной документации есть ошибки в инструкции для новичков.
  2. AvaloniaUI. Это более популярный и проработанный фреймворк, который позволяет создавать интерфейсы как для мобильных устройств, так и для Linux и OS X. Также в нём используется диалект XAML, что будет плюсом для тех, кто пробовал создавать приложения для Windows. В нём даже есть поддержка MVVM.

Я попробовал оба, и второй показался мне более удобным: в нём есть язык разметки, поддержка MVVM, быстрая установка, лёгкий переход с WPF. Поэтому я выбрал его.

Я буду создавать приложение в Linux Ubuntu, но эта инструкция подойдёт всем, кто использует .NET Core. Создавать приложения можно и в Visual Studio, скачав для него расширение, но так как его нет на Linux, я буду пользоваться терминалом.

Для начала клонируйте себе на компьютер этот репозиторий:

В нём находятся шаблоны для создания приложения с AvaloniaUI. Если вы не умеете пользоваться Git, то просто скачайте содержимое и распакуйте куда-нибудь на компьютере. Затем откройте консоль и введите следующую команду:

dotnet new --install [путь к скачанному репозиторию]

Она установит шаблоны для создания приложения. Чтобы проверить, добавились ли шаблоны, используйте команду:

Вы увидите список всех установленных шаблонов. Среди них должны быть Avalonia Window, Avalonia .NET Core MVVM App, Avalonia UserControl и Avalonia .NET Core App. Если они на месте, можно продолжать.

Откройте в консоли папку, в которой хотите создать проект, и введите:

Будет создано приложение с использованием MVVM. Практически вся документация по AvaloniaUI написана с использованием этого паттерна, поэтому проще будет разрабатывать на нём.

Теперь можно приступать к работе над приложением.

У вас будут созданы следующие папки

  • Assets — сюда можно загружать различные компоненты программы вроде иконок, изображений, звуков и прочего.
  • Models — эта папка предназначена для классов, которые будут выступать в роли модели.
  • ViewModels — здесь находятся классы-посредники между видом и моделью.
  • Views — все окна будут находиться здесь.

Сначала посмотрим в файл Program.cs в корневом каталоге:

using System;
using Avalonia;
using Avalonia.Logging.Serilog;
using AvaloniaMVVM.ViewModels;
using AvaloniaMVVM.Views;

namespace AvaloniaMVVM
{
	class Program
	{
    	// Initialization code. Don't use any Avalonia, third-party APIs or any
    	// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
    	// yet and stuff might break.
    	public static void Main(string[] args) => BuildAvaloniaApp().Start(AppMain, args);

    	// Avalonia configuration, don't remove; also used by visual designer.
    	public static AppBuilder BuildAvaloniaApp()
        	=> AppBuilder.Configure<App>()
            	.UsePlatformDetect()
            	.LogToDebug()
            	.UseReactiveUI();

    	// Your application's entry point. Here you can initialize your MVVM framework, DI
    	// container, etc.
    	private static void AppMain(Application app, string[] args)
    	{
        	var window = new MainWindow
        	{
            	DataContext = new MainWindowViewModel(),
        	};

        	app.Run(window);
    	}
	}
}

Нас интересует метод AppMain (). В нём создаётся окно (MainWindow) с указанием DataContext (используется для привязки данных), а потом это окно запускается.

В этом методе можно определить свою логику инициализации приложения. Например, объявить экземпляр модели и передать его в конструктор MainWindowViewModel (). Однако перед этим нужно определить конструктор, который будет принимать такой аргумент.

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

Для начала нужно подключить пространство имён ReactiveUI, которое в AvaloniaUI используется для реализации паттерна MVVM:

Затем можно писать сам код:

private string _message = "";

private string _num1 = "0";
private string _num2 = "0";
private string _result = "0";

public void Click()
{
    int num1 = 0;
    int num2 = 0;
    int result = 0;
    Message = "";

    try
    {
   	 num1 = Convert.ToInt32(Num1);
   	 num2 = Convert.ToInt32(Num2);
    }
    catch(Exception e)
    {
   	 Message = "Wrong input!";
   	 Console.WriteLine(e.Message);
    }

    result = num1 + num2;

    Result = result.ToString();
}

public string Message //Так свойства используются для привязки в ReactiveUI
{
    get => _message;
    set => this.RaiseAndSetIfChanged(ref _message, value);
}

public string Num1 
{
    get => _num1; 
    set => this.RaiseAndSetIfChanged(ref _num1, value);
}


public string Num2
{
    get => _num2;
    set => this.RaiseAndSetIfChanged(ref _num2, value);
}

public string Result
{
    get => _result;
    set => this.RaiseAndSetIfChanged(ref _result, value);
}

Теперь нужно написать код интерфейса для окна в файле MainWindow.xaml:

<Window xmlns="https://github.com/avaloniaui"
   	 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   	 xmlns:vm="clr-namespace:AvaloniaMVVM.ViewModels;assembly=AvaloniaMVVM"
   	 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   	 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   	 mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
   	 x:Class="AvaloniaMVVM.Views.MainWindow"
   	 Icon="/Assets/avalonia-logo.ico"
   	 Title="AvaloniaMVVM">

    <Design.DataContext>
   	 <vm:MainWindowViewModel/>
    </Design.DataContext>

    <Grid>
   	 <Grid.RowDefinitions>
   		 <RowDefinition Height="1*"/>
   		 <RowDefinition Height="2*"/>
   		 <RowDefinition Height="1*"/>
   		 <RowDefinition Height="2*"/>
   		 <RowDefinition Height="1*"/>
   	 </Grid.RowDefinitions>

   	 <Grid.ColumnDefinitions>
   		 <ColumnDefinition Width="1*"/>
   		 <ColumnDefinition Width="2*"/>
   		 <ColumnDefinition Width="1*"/>
   		 <ColumnDefinition Width="2*"/>
   		 <ColumnDefinition Width="1*"/>
   		 <ColumnDefinition Width="1*"/>
   	 </Grid.ColumnDefinitions>

   	 <TextBox Text="{Binding Num1, Mode=TwoWay}" Grid.Row="1" Grid.Column="1"/>
   	 <TextBlock Text="+" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Grid.Column="2"/>
   	 <TextBox Text="{Binding Num2, Mode=TwoWay}" Grid.Row="1" Grid.Column="3"/>

   	 <Button Content="=" Grid.Row="2" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Command="{Binding Click}"/>

   	 <TextBlock Text="{Binding Result}" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="3" Grid.Column="2"/>
   	 <TextBlock Text="{Binding Message}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Red" Grid.Row="4" Grid.Column="2"/>
    </Grid>
</Window>

Вы можете заметить, что это практически тот же XAML, который используется в WPF: тут такие же компоненты и свойства, так же используются Grid и привязка данных. Однако здесь в качестве команды можно указывать обычные методы, чего нельзя делать в WPF.

Чтобы скомпилировать и запустить приложение, введите в консоли следующую команду:

Результат должен получиться таким:

Теперь приложение можно просто скомпилировать для разных ОС — никаких дополнительных манипуляций для переноса на новую платформу не требуется.

10–15 лет назад это показалось бы извращением, но сейчас мы можем писать программы для Linux на языке, который изначально был предназначен для разработки приложений под Windows.

Учись бесплатно:
вебинары по программированию, маркетингу и дизайну.

Участвовать

Этот материал написан посетителем сайта, и за него начислено вознаграждение.

Как решить проблему (реальность)

Начну без лишних предисловий.

В первой части я выдвинул ряд условий которые приложение должно соблюдать по возможности:

рекомендации

RTX 3070 Ti за 55 тр — цена как при курсе 62

<b>13900K</b> в Регарде по СТАРОМУ курсу 62

S23 Ultra — цены нехило пошли вниз

Компьютеры от 10 тр в Ситилинке

MSI 3060 за 30 тр в Регарде

Много 4080 от 100тр — цены в рублях не растут

16 видов <b>4070 Ti</b> в Ситилинке — от 80 тр

3070 Gigabyte Gaming за 50 тр с началом

3070 Gigabyte Gaming за 50 тр в Регарде

3060 Ti Gigabyte дешевле 40 тр в Регарде

13700K дешевле 40 тр в Регарде

Вакансия: Автор новостей широкого профиля

3080 за 70тр с началом несмотря на курс

3060 дешевле 30тр цена — как при курсе 68

15 видов 4090 в Ситилинке по норм ценам

Ищем PHP-программиста для апгрейда конфы

13600K дешевле 30 тр в Регарде

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

2) Приложение обязано работать в любом дистрибутиве Linux насколько это возможно.

3) Приложение не должно иметь лишних зависимостей, просто чтобы в один момент не утонуло в болоте зависимостей.

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

5) Приложение обязано сохранять своё «лицо» в каком бы дистрибутиве его не запустили, иначе говоря внешний вид приложения не должен зависеть от дистрибутива Linux.

Настало время приступить к реализации приложения, и посмотреть, сможет ли моё приложение удовлетворить выдвинутый ряд условий.

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

Так каким образом я собрался решать проблему распространения и запуска приложений в Linux дистрибутивах?

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

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

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

Все же я делаю приложение не для Windows, где все по полочкам и стандартно, а если что-то сломалось то Microsoft пробует это исправлять… Нет, Linux суров и беспощаден, потому нужно разрабатывать независимое и действительно свободное ПО, а не мусор, который падает от любого дуновения ветра в болоте зависимостей.

Так вот, однажды сидя за разработкой игры в GODOT я вспомнил один забавный факт из своего прошлого…

Когда изучал C++ и писал софт на этом языке, я однажды использовал OpenGL для отрисовки рабочей зоны приложения, хоть программирование на C++ я давно забросил, но вот опыт и знания никуда не исчезли, хотя и устарели «немного».

И тут я понял, ведь GODOT позволяет разрабатывать кроссплатформенные игры и скомпилированные исполняемые файлы прекрасно работают везде, так почему бы не тряхнуть стариной и не написать приложение интерфейс которого будет нарисован при помощи OpenGL?

Звучит безумно, использовать игровой движок для написания программы… Но я неоднократно примечал в своих статьях, игра это и есть программа, так что безумного в том, чтобы разработать не игру, а программу используя ПО предназначенное для разработки игр?

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

Ведь «игра» скомпилированная при помощи GODOT Engine требует от системы поддержку OpenGL и базового функционала что обязан быть абсолютно везде, по сути движок просто вызывает OpenGL окно и работает, таким образом у разработчика есть безграничные возможности оформления приложения, ведь он может сделать что угодно, хоть в 3D с шейдерами.

Кто-то заикнется про потерю кастомизации? А она разве есть в линуксах? Что может обычный пользователь кастомизировать в том же Xfce? Да ничего толком, меньше чем даже в Windows 7…

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

А что до потребления ресурсов? А разве линуксоиды уже не положили здоровенный болт на этот нюанс выпиливая поддержку x86 и выкидывая всякие Flatpak? Так какая разница, качать приложение в виде Flatpak где 1 МБ приложение + 999 МБ зависимостей, или качать исполняемый пакет изначально без зависимостей весом 999 МБ, который при этом не вынесет мозг пользователю как всевозможные DEB/AppImage/Flatpak и прочий мусор?

Да, в моем случае каждое приложение будет вызывать OpenGL окно, а это занимает память на видеокарте, но разве это сейчас проблема? Или в линуксах драйвер не осилит «аппаратное ускорение» для десятка приложений одновременно? Так это проблема не пользователя или разработчика, это проблема операционной системы тогда.

В любом случае GODOT Engine позволяет написать действительно независимые приложения/игры, которые может запустить обычный пользователь без особых проблем, и оно будет работать практически везде, за что огромное уважение с моей стороны разработчикам GODOT Engine: ( https://godotengine.org/ — https://github.com/godotengine/godot ).

Пожалуй пора перейти к реализации.

Первые реализации

Первая моя реализация выглядит вот так, и название ему «Chi Calculator»:

Да, это ужасно, но оно работает, со временем я продолжал писать код и экспериментировать:

И вот мое приложение работает не только в среде Windows, но и в Linux:

Формирование инструментов для разработки и сборки

Дальше я решил выпустить свой «калькулятор» и под Android, ох и повозился же я пока собрал набор инструментов необходимый, чтобы скомпилировать под Android, линуксоидность во всей красе…

С одной стороны Google молодцы, выпустили Android SDK в виде установочного пакета жирного, якобы можно установить и использовать! Но нет, скачать установочный пакет мало, нужно еще выкачать тонну зависимостей которые по факту должны были идти вместе с самим SDK.

Вот за что я ненавижу дистрибутивы Linux в том виде, в котором они существуют, утопает в зависимостях что скармливают строго через репозитории в интернете, а что если эти репозитории будут скомпрометированы или недоступны, а человеку нужны эти инструменты? Как ему быть без адекватных установочных пакетов в запасе которые бы содержали в себе все самое необходимое? И мне еще будут что-то рассказывать как в линуксах все прекрасно и никаких проблем…

Хотя сейчас я не в среде Linux, я в среде Windows, но это болото зависимостей через интернет даже в среду Windows умудрились затащить, отвратительно.

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

В архиве есть сам GODOT Engine v3.5.1 (Windows/Linux), RCEDIT (Windows/Sources), Android SDK (Windows).

Да, текущий архив преимущественно будет работать только в среде Windows, ибо Android SDK у меня для Windows, пользователям Linux дистрибутивов нужно будет сосать зависимости самим, но в будущем я скорее всего сформирую такой пакет независимой разработки и для Linux.

Кто-то скажет что такой пакет безумие и вообще не нужно было делать, но извините, я предоставил инструменты как единое целое, разве это плохо? Разве плохо когда заинтересованный моим проектом разработчик может в два клика скачать и настроить среду разработки?

Или тонуть в зависимостях и «404 Not Found» это истинный путь линуксоидов? Когда человек заинтересовался проектом, а сделать ничего не может просто потому что репозиторий с инструментами потерялся, или в репозиториях все обновилось и оно больше не работает как положено.

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

Текущая версия 1.2

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

Собственно есть и репозиторий: ( https://github.com/Shedou/Chi-Calculator )

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

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

Сейчас у меня настроен экспорт для Windows (x32/x64), Linux (x32/x64), Android (ARMv7, ARMv8, x86, x86_64).

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

По итогу мой «калькулятор» работает как в среде Windows, так и в среде Linux, даже в Android.

Да, здесь для демонстрации я взял устаревшую версию «калькулятора», но суть это не меняет.

А вот и калькулятор на старой Lenovo P70-A с Android 5.1.1, зря я не прихватил с собой старый GT-i8552 на четвертом андроиде…

Хотя есть человек который проверил в Android 4.4.2 мой «калькулятор», и оно работает:

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

Кое-что забыл…

Раз уж пишу статью, то почему бы не указать ссылку на свой блог?

Создаю «Link Button», указываю название, и создаю «связь» с главным скриптом.

В скрипте добавляю всего одну строчку со ссылкой, повторяю для ссылки на GitHub проекта, а дальше просто компилирую версию 1.3…

Так как я сейчас работаю используя мобильный интернет, а безлимитный тариф закончился (расходую трафик), то не вижу смысла компилировать все возможные версии приложения:

Как оно теперь работает? Легко и просто, вот пример на Android 5.1.1, ссылки работают как положено, правда смартфон не подключен к сети, потому загрузить сайт не выйдет.

Тестирование приложения в разных дистрибутивах

У меня был безлимитный интернет еще недавно, но безлимит закончился и сейчас я использую трафик.

Так вот, пока у меня был безлимитный трафик я скачал пачку разнообразных дистрибутивов, вдобавок отсортировать весь этот зоопарк и докинул дистрибутивы которые у меня уже были в наличии, итого это все весит целых 162 гигабайта…

Да, я собрал не очень большой зоопарк, но этого хватит пока что.

Меня особенно взбесили разработчики Manjaro Linux, они бросили поддержку x86, но они бросили не только x86, они бросили пользователей которым нужен x86 дистрибутив, просто негде скачать старые версии Manjaro, я так и не смог найти в интернете нужный дистрибутив…

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

Microsoft тоже неохотно предоставляет образы старых систем, но Windows популярна и скачать оригинальный образ можно на любом торренте, а что делать в помойке дистрибутивов, популярность которых это 2.5 человека…

Ладно, дистрибутивы я скачал, теперь их установить нужно… VirtualBox конечно мне поможет в этом, но есть проблема, мне нужно очень много места для виртуальных машин, а SSD у меня уже заполнены…

Я как-то писал статью про свой компактный ПК и меня упрекали, мол, купил бы я себе ноутбук да не возился с маленьким системным блоком, давайте, поговорите мне тут, как я в ноутбук запихну 4 SATA накопителя + NVMe? Пихать в ноутбук один массивный NVMe SSD и сосать лапу если он внезапно выйдет из строя? Спасибо, обойдусь как-нибудь компактным ПК, я не камикадзе чтобы все хранить в одном накопителе.

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

Пока освобождаю SSD перенося данные на HDD можно удалить лишние виртуальные машины:

А дальше я буду создавать виртуальные машины для каждого дистрибутива что меня заинтересует.

Да, это все рутина, но как я докажу что моё приложение действительно работает и не зависит от конкретных дистрибутивов Linux?

И вот я установил всего две операционные системы в виртуальные машины, «debian-live-11.6.0-amd64-xfce+nonfree» и «debian-live-11.6.0-i386-kde+nonfree», как думаете, все прекрасно работает? Прямо как вскрикивают «не фанаты»?

А вот обломитесь! Я хочу увеличить разрешение экрана, ибо 800×600 ну совсем неприлично выглядит для моего монитора… Иду в настройки, пытаюсь изменить разрешение, в Debian Xfce изменилось нормально, а вот Debian KDE наотрез не желает менять разрешение экрана, на мгновение изменяет (первый скриншот) и сразу же откатывает до 800×600 (второй скриншот).

Linux дистрибутивы прекрасны? Никаких проблем? Все работает у всех идеально? Да? Рассказывайте сказки, вдруг поверит кто-нибудь… Ладно, делать нечего, буду некоторые виртуальные машины держать в разрешении 800×600…

С Fedora 37-1.7 тоже не задалось… Она явно не очень хорошо дружит с разрешением 800×600, а еще Fedora сама установила дополнения VirtualBox (кто её просил?), в итоге растянув окно виртуальной машины и Fedora растянулась, правда вот лучше бы она этого не делала…

Через настройки дистрибутива установил стандартное разрешение 1024×768, но это не сильно помогло, все же это сам интерфейс системы кривой такой… Я уже боюсь продолжать установку остальных дистрибутивов, какие еще «грабли» меня ждут…

Далее я «осуслился» в зависимости, я не могу дать доступ к интернету, у меня всего 8 ГБ трафика, и не хотелось бы его потерять просто на установке OpenSUSE…

Немного поковырявшись я таки смог начать установку, операционная система при запуске накатила дополнения VirtualBox, вот кто её просил? Ну и ради интереса проверил разрешение экрана, оно работает здесь, вероятно не без помощи дополнений установленных без моего разрешения.

Особое внимание заслуживают дистрибутивы «gentoo livegui-amd64-20230205T170201Z.iso» и «slackware64-live-15.0.iso», они заслуживают почётное место самых странных дистрибутивов, ведь Gentoo невозможно установить из Live образа, а Slackware просто закрыт паролем…

Эй, разработчики! Зачем это было создано? У вас какой-то синдром неведомый, что заставляет разрабатывать такие вещи?

Конечно, если посмотреть внимательнее то пароль вполне можно найти, но вашу кочергу… На рабочем столе есть ярлык «Install Slackware», и этот ярлык открылся от одиночного нажатия по нему, похоже будет «весело»…

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

В итоге потрачено пол дня, а из пригодного установилось и работает только Debian, Fedora и OpenSUSE…

Что за безумием я занимаюсь вообще в этой статье… Но я еще установил Simply Linux 10.1, установщик конечно не идеален, но он хотя бы визуально не угнетает, все просто и понятно сделано, у меня совершенно не возникло проблем при установке, будто устанавливаю Windows, только лучше…

Система загрузилась не спрашивая логин/пароль, точно как я указал при установке, пока меня очень радует дистрибутив, не может ведь быть все настолько хорошо…

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

А вот дальше меня ждал «сюрприз», браузер криво работает, и причина этому скорее всего VirtualBox со своими кривыми драйверами видеокарты…

В остальном я не заметил явных проблем, даже окна можно растягивать без проблем несмотря на окружение Xfce, разработчики дистрибутива очень хорошо поработали над мелочами, в той же Xubuntu просто нереально растянуть окно, ибо границу в 1 пиксель крайне тяжело «словить» курсором.

Этот дистрибутив определенно заслужил «мини обзор» в этом разделе статьи, даже иконки в проводнике нормально отображены, нет никаких громадных зазоров, сами иконки легко можно различить просто окинув взглядом.

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

Еще отмечу Endeavour OS, тоже на удивление неплохой установщик был, только вот в системе мне постоянно вылазят навязчивые уведомления, что нет доступа к интернету… Впрочем, сойдет, оно хотя бы работает.

Думал я устанавливать Manjaro еще, но пожалуй не буду, я её немного боюсь, как бы не сломалась случайно от дуновения ветра…

Пора бы сказать «СТОП», но я хочу еще установить ROSA Linux (ROSA.FRESH.LXQT.12.2.i686.iso), и знаете, меня опять порадовал установщик.

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

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

Но чем действительно меня удивил этот дистрибутив, так это «выключением», здесь не напрягают спрашивая дважды «а хочешь ли ты выключить, или может что-то другое сделать?»…

Вот серьезно, я похож на идиота когда нажимаю кнопку «выключить»? Пользователь нажимает кнопку «выключить», так на кой хрен ему предлагают целый набор кнопок подразумевая «а может все же перезагрузить, или выйти из системы…»? Вот этого недостатка ROSA Linux (ROSA.FRESH.LXQT.12.2.i686.iso) не имеет, и за это очередной плюс разработчикам.

Все, пожалуй хватит дистрибутивов Linux… Иначе я до утра буду сидеть за ПК…

Я собрал два 32 разрядных дистрибутива, и пять 64 разрядных, и постарался чтобы были разные графические интерфейсы у систем, чтобы наверняка все поломалось что только может при обычной разработке софта под Linux дистрибутивы.

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

Естественно я использую 7-Zip, 256 МБ словарь чтобы эффективнее сжимало, блок по размеру файла чтобы была возможность быстро распаковать один единственный файл из архива не распаковывая его полностью, ну и слежу чтобы не слишком много памяти это занимало, очень жаль что нет такого функционального интерфейса в дистрибутивах Linux.

Да, архивация задача не из простых, у меня даже браузер начал слегка подтормаживать…

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

Мне не нужны системы контроля версий в данном случае, потому отправить все в архивы самый оптимальный вариант для меня.

Так вот, надеюсь никто не забыл про что вообще та статья была?

Во всех дистрибутивах мой «калькулятор» прекрасно заработал и сохранил своё «лицо» в какой бы обстановке он не находился, причем в некоторых дистрибутивах заработала как x86 версия, так и x64 одновременно.

Конечно я переборщил немного, 7 дистрибутивов сложно разложить не перекрывая «соседей» имея монитор разрешением всего 2560×1440, но это более чем наглядно демонстрирует результат.

Заключение

Выполнил ли я ранее поставленные условия? Очень даже выполнил.

Мой «калькулятор» работает в среде Windows (само собой), он работает даже в среде Android 4.4.2 и Android 5.1.1, он работает в разных дистрибутивах Linux, даже тогда, когда браузер в дистрибутиве работает неправильно по вине кривого драйвера видеокарты VirtualBox, но это оказалось не проблема для моего приложения.

Причем важно заметить, дистрибутивы Linux я устанавливал без доступа к интернету, как минимум потому что сейчас у меня мобильный интернет на трафике, и трафика не очень то много, но это не проблема для «калькулятора», ведь его один раз скачал и скопировал хоть на десяток разных ПК.

Не нужно насиловать репозитории скачивая одно приложение дважды на несколько систем…

Ранее я как-то сказал:

«Сейчас дистрибутивы Linux не способны стать в один уровень с Windows по многим причинам, и одну из таких причин я решил устранить сам, ведь на сообщество Linux надежд больше нет, более 20 лет безрезультатно месить болото зависимостей даже не догнав Windows 98 по некоторому базовому функционалу… Это просто… Я не знаю как это назвать без ругани…

Зачем вообще создают дистрибутивы Linux если их невозможно использовать адекватно, обычный пользователь постоянно обретает бесконечные проблемы которых быть в принципе не должно…

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

Так вот, используя GODOT Engine я буквально за несколько дней решил одну из самых серьезных проблем дистрибутивов Linux, проблему распространения и запуска софта.

Да, мой «калькулятор» по факту мусор, но этот мусор работает везде, и сохраняет свое «лицо» в каком бы дерьме он не находился, а может ли так какой-нибудь Pencil Project? Сейчас проверим, даже трафик не пожалею…

Пока это приложение качалось я уже был готов признать что был не прав, и DEB пакеты очень даже годная штука, но чудес не случилось…

Простое открытие пакета запускает архиватор.

В списке приложений я нашел потенциально полезную программу, судя по названию «Synaptic Package Manager» уж точно должен что-то сделать, но и тут облом…

Ну ладно, полез я в терминал, а в терминале система показывает мне (пользователю) средний палец…

Ладно, иду в интернет «гуглить», возвращаюсь в терминал, чтобы отомстить за прошлое «поражение», но и тут облом…

В общем ничего не изменилось, все такое же ущербное как и было, время потратил? Потратил, результат получил? Не получил, и потом линуксоиды будут что-то заливать про кривые руки и прочий бред всевозможный, лишь бы защитить свою кривую «любимицу».

А теперь посмотрим на сводку результатов которые я достиг за несколько дней:

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

Еще можно заметить последствия отказа от x86, многие дистрибутивы просто не существуют больше в виде x32, а ряд x64 дистрибутивов просто не могут запустить 32 разрядное приложение, только Simply Linux 10.1 смог запустить x32 и x64 версию приложения одновременно.

А вот Debian 11.6.0 x64 разочаровал, он не смог запустить x32 версию приложения, хотя и есть x32 версия дистрибутива.

Единственный мой просчет это дистрибутив ROSA Linux, стоило установить еще x64 версию дистрибутива, вдруг она смогла бы запустить x32 версию приложения.

А теперь дружки пирожки попробуйте сказать еще раз все что вы сказали в предыдущей части статьи:

Давайте, отрицайте факты, а я посмеюсь продолжая свою работу дальше.

Стыд и позор, за десятилетия не решить проблему зависимостей, распространения и запуска приложений в дистрибутивах, когда я, криворукий и тупой (по мнению линуксоидов) эту проблему «решил» буквально за несколько дней, и таки создал приложение которое можно без проблем распространять и запускать…

И да, еще раз повторю, огромное уважение от меня разработчикам GODOT Engine, именно таким должен быть софт для Linux: ( https://godotengine.org/ — https://github.com/godotengine/godot ).

Репозиторий приложения Chi Calculator: ( https://github.com/Shedou/Chi-Calculator ).

На этом я закончу статью, но не работу.

Благодарю за внимание, больше интересных статей в блоге Hard-Workshop.

Этот материал написан посетителем сайта, и за него начислено вознаграждение.

Hola, Amigos!

С вами команда Amiga. Мы занимаемся заказной разработкой мобильных приложений, создаем веб-сайты и корпоративные порталы.

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

Разработка приложения на Flutter — это разработка с нуля, что подразумевает большую подготовительную работу. Наш заказчик, компания Vaillant Group, пришел к нам именно с такой задачей, поэтому мы предложили Flutter как самое оптимальное решение.

Мы разработали кроссплатформенное мобильное приложение с интеграцией программы лояльности для компании по производству оборудования для отопления, охлаждения и вентиляции помещений Vaillant.

Это приложение для сервисных специалистов, чтобы помочь им облегчить процесс регистрации работ и привлечь в программу лояльности PRO.Expert. В ней можно начислять, копить и выводить баллы на банковский счет или же потратить их внутри приложения в разделе «витрина подарков».

Почему выбрали Flutter?

Мы решили использовать кроссплатформенную разработку и технологию Flutter — она позволяет создавать приложение одновременно на двух платформах: Android и iOS.

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

Тимур Моисеев, Teamlead Amiga

В разработке на Flutter есть и другие преимущества:

  • Оптимизация бюджета. Создание приложения на Flutter стоит на 40% дешевле, чем разработка двух нативных. А с пользовательской стороны нет разницы.
  • Одинаковая бизнес-логика на всех платформах. Вся инфраструктура приложения выглядит нативно за счет особенностей фреймворка Flutter.
  • Ускоренный релизный цикл. Приложение на Flutter запускается быстрее, чем нативное, за счет работы с одной командой и на одной платформе. Значит и прибыль компании оно принесет быстрее.
  • На Flutter можно реализовать любой дизайн: от каталогов интернет-магазина до сложных анимаций.

Какие задачи проекта?

Мы подключили аналитика, разрабатывали дизайн-системы, проектировали back-end часть, занимались проработкой коммуникации с пользователями и интегрировали программу лояльности PRO.Expert.

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

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

Как выглядит приложение?

Раньше каждый раз при входе в приложение нужно было вводить логин и пароль, это неудобно. Мы провели интеграцию с системой Keycloak. Теперь при первой авторизации передается долгоиграющий токен, который месяц позволяет пользователю не вводить данные для входа.

Регистрация специалиста

При регистрации доступен выбор роли: для каждого рода деятельности предусмотрен свой функционал и особенное накопление баллов. Flutter позволяет продумать бизнес-логику так, чтобы пользователю на любой платформе было интуитивно понятно заполнять данные.

Личный кабинет

В личном кабинете специалиста можно посмотреть баллы, в один клик перевести их на карту или приобрести подарок.

Регистрация работ

Раньше монтажники вводили адрес работ «от руки». Это занимало в среднем 5 минут, можно было допустить ошибки. Мы интегрировали сервис Da.Data – сервис справочников, и теперь это занимает до 30 секунд. Но из-за того, что долгое время сервисные специалисты вводили неверные адреса, нам нужно было сохранить старую базу и сметчить ее с новой. Как проблема решилась: мы придумали нелинейную систему, которая проверяет условия корректного ввода данных. Часть решения перенесли на back, часть на front.

Автоматическая регистрация работ

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

Офлайн-регистрация

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

Подведем итоги

Мы реализовали полностью рабочее мобильное приложение на Flutter с нуля, продолжаем его поддерживать и развивать. Сейчас программу лояльности приостановили, но приложение продолжает функционировать, баллы за регистрацию работ копятся, их можно будет вывести, как только PRO.Expert возобновится.

Приложение можно скачать в App Store и Google Play, а с сентября 2022 и в Huawei AppGallery.

За всеми согласованиями, сметами и проектирование бывает, что теряется цель проекта. Но это не тот случай. Мы общались с отделом продаж, маркетинга, специалистами по программе лояльности, чтобы собрать полный список ожиданий. Было приятно сотрудничать с командой специалистов, которые знают, чего хотят. От команды Vaillant мы также получили много положительных отзывов о подходе к работе.

Софья Винникова, системный аналитик Amiga

У нас большие планы на развитие приложения PRO.Expert. Система лояльности сейчас работает в энергосберегающем режиме, но в скором времени возобновится. Сейчас мы работаем над улучшением каталога продукции в приложении, разрабатываем дополнительный функционал по геопозиционированию. Уверен, что дальнейшая работа с командой Amiga будет такой же эффективной и плодотворной!

Артем Растунов, директор по маркетингу Vaillant

Мы очень ценим нашу команду и хотим отметить их в статье

Сергей Лепшей – PM

Софья Винникова – Системный аналитик

Кирилл Калюжный – Flutter dev

Тимур Моисеев – Flutter dev

Игорь Веденеев – Mobile TeamLead

Леонид Никулин – Арт-директор

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


Что такое кроссплатформенная разработка и как обеспечивается

Кроссплатформенная разработка – это процесс, при котором создается программный продукт, способный взаимодействовать с несколькими операционными системами. Если речь заходит о разработке мобильного приложения, то это будет приложение, которое сможет работать как на Android, так и iOS-устройствах. При этом всем программа способна стабильно функционировать на всех аппаратных платформах.

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

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

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

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


В каких случаях нужна кроссплатформенная разработка

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

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

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

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


Особенности, преимущества и недостатки кроссплатформенной разработки

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

Начнем с того, что по сравнению с нативной разработкой, затраты на создание кроссплатформенных приложений ниже на 25-30% (зависит от инструментов, которые вы используете). Учтите, что при использовании нативной разработки код для программных продуктов пишется по отдельности для каждой платформы. Следовательно, вы будете тратить вдвое больше времени и сил. Что же касается кроссплатформенных продуктов, то здесь перерабатывается только часть кода, поэтому многое остается неизменным.

Какие еще преимущества может предложить мультиплатформенность:

  1. Гораздо меньше ошибок. Как говорилось ранее, для каждой операционной системы используется одна и та же база кода, поэтому допустить какие-либо ошибки довольно сложно.
  2. Оперативность создания проекта. Речь идет не только о высокой скорости разработки продукта. Самое главное, что перед выпуском программы вам не придется тратить время на доработку кодификации с последующим ее переводом на другую платформу.
  3. Нет необходимости нанимать большой штат. Один из плюсов в том, что для изготовления кроссплатформенного приложения можно нанять всего одного разработчика-универсала.
  4. Привлечение новых клиентов. Так как программный продукт может размещаться в нескольких магазинах (Google Play и App Store), у вас будет возможность набрать базу клиентов гораздо быстрее.
  5. Код можно использовать повторно. Если каждая нативная программа пишется с нуля, то в случае с кроссплатформенными утилитами все гораздо проще. В процессе разработки, как правило, используются готовые блоки, которые можно менять в дальнейшем или применять для других утилит.

Овнеры магазинов ФБ акков про свой бизнес и тренды в арбитраже. ФБ аккаунты для арбитража трафика

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

Однако не стоит забывать, что у кроссплатформенной разработки есть и свои минусы:

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

  1. Запоздалые обновления. Новые версии мобильных операционок постоянно обзаводятся новыми обновлениями. Однако их нельзя встроить в мультиплатформенные утилиты, пока они не появятся в среде разработки. Также есть вероятность того, что некоторые функции вообще не получится реализовать. В результате некоторых клиенты могут остаться недовольны.
  2. Тяжело найти ошибки. Так как код в мультиплатформенном приложении общий, то в случае появления ошибки она будет распространяться на все платформы. При этом отыскать источник ошибок будет гораздо сложнее, чем в нативных программах.
  3. Большой объем приложения. Еще один минус кроссплатформенных приложений заключается в большом объеме кода, в результате чего программа занимает больше места на устройстве.

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


Как разрабатывать кроссплатформенные приложения

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

Какие действия нужно предпринять:

  1. Для начала нужно продумать общую идею продукта и составить концепцию. Помочь в этом может внимательный анализ конкурентов и целевой аудитории.
  2. Далее нужно подобрать язык программирования. Конечно, тут многое зависит от ваших навыков и финансовых возможностей.
  3. На следующем этапе подберите фреймворк, с помощью которого будет осуществляться разработка. Список лучших решений мы рассмотрим ниже.
  4. Продумать дизайн и особенности интерфейса, после чего внедрить функционал.
  5. Провести тестирование и в случае успеха разместить продукт в магазинах.

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


Какие инструменты использовать для кроссплатформенной разработки

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

Если вам нужно получить действительно качественный продукт, рекомендуем обратить внимание на следующие варианты.

React Native

Считается одним из самых эффективных инструментов для разработки кроссплатформенных приложений. Ключевой особенностью считается открытый исходный код, принадлежащий компании Meta*. Многие специалисты используются данный фреймворк для создания универсальных программных продуктов. Стоит отметить, что по сравнению с другими средами разработки, React Native позволяет делать приложения более функциональными.

К достоинствам фреймворка относятся:

  • удобочитаемый код;
  • поддержка ведущих IDE;
  • возможность применения фреймворков JS для внедрения новых функций;
  • поддержка функции Hot Reloading, благодаря которой пользоваться единым кодом можно на разных операционках;
  • широкий выбор готовых блоков;
  • возможность применения при JavaScript.

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


Xamarin

Еще один фреймворк с открытым исходным кодом, позволяющий создавать приложения для операционных систем Android и iOS. Одна из особенностей Xamarin – возможность разработки уникальных пользовательских интерфейсов, которые можно адаптировать под любую мобильную платформу. Функционирует фреймворк на языке С#, следовательно, для его запуска можно применять Visual Studio 2019.

Главное достоинство Xamarin – обеспечение полноценной кроссплатформенной поддержки с совместным использованием кода до 90%. Стоит учесть, что такой подход не только экономит средства на разработку, но и сокращает время на тестирование и запуск утилиты. Также радует поддержка инструментов Xamarin.Android/iOS и Xamarin.Forms. С помощью последнего можно ускорять процесс разработки.


Appcelerator

Главная особенность данного фреймворка – использование кода JavaScript на базе Alloy MVC с возможностью создания программных продуктов для разных операционных систем. Благодаря такому подходу программисты могут создавать качественные приложения в кратчайшие сроки без особых затрат.

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

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


PhoneGap

Неплохой инструмент для разработки мультиплатформенных утилит на базе JS. Обратите внимание, что фреймворк представляет собой комплект HTML-страниц, которые хранятся в облаке и обернуты в нативную оболочку.

Для работы с инструментом необходимо владеть языками CSS и HTML. При запуске продукта на смартфоне доступ к функционалу предоставляется специальными встроенными плагинами. Производительность фреймворка заметно уступает конкурентам, однако внимания заслуживает интуитивно понятный интерфейс с приятным оформлением.


Lonic

Главная задача инструмента – создание кроссплатформенных приложений гибридного типа. Для работы в фреймворке используется язык JavaScript. Если же вам нужно разработать сложную программу, тогда потребуется владение HTML и CSS.

Одной из особенностей является возможность взаимодействия со средой разработки Apache Cordova, благодаря чему вы можете преобразовывать веб-программы в мобильный контент. Также Lonic славится тем, что поддерживает множество дополнительных инструментов, включая различные виджеты и визуальные элементы. Освоить работу с платформой достаточно легко. Главное – иметь опыт взаимодействия с React Native.


Flutter

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

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

Есть несколько особенностей Flutter:

  • Простота разработки. По большей части это достигается за счет функции горячей перезагрузки, позволяющей мониторить результаты кода и исправлять ошибки без перезагрузки программы.
  • Минимум тестирований. При разработке приложений через Flutter используется единая кодовая база. Следовательно, автоматические тесты пишутся всего один раз.
  • Оптимальный вариант для разработки MVP. Так как сервис отличается высокой скоростью загрузки страниц и простым пользовательским интерфейсом, он идеально подходит для создания минимально жизнеспособного продукта.

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

Вывод

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

Занимались разработкой мобильного приложения?

1 голос


Да — 100%



Нет — 0%

Понравилась статья? Поделить с друзьями:
  • Как написать куратору что тебе плохо
  • Как написать куратору что заболел
  • Как написать куратору что болит живот
  • Как написать куратору об отчислении
  • Как написать критическую статью на литературное произведение