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

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

Splice - защитник, соратник современного музыканта. Мы разработали центр создания, который соединяет рабочую станцию ​​музыканта с облаком, что означает, что мы сидим рядом с музыкантом, пока он выполняет свой процесс создания. Мы заранее выбрали прозрачную, незаметную и независимую интеграцию, что означает, что у нас есть приложение, работающее в фоновом режиме, обрабатывающее различные события и представляющее пользовательский интерфейс только при необходимости (аналогично Dropbox). Более сложные действия были разработаны для работы в сети, требующей от пользователя открытого браузера. Короче говоря, Splice невероятно успешен, но современные музыканты считают, что браузер часто находится слишком далеко от места их творчества и отвлекает их. У нас есть собственные приложения, написанные на Objective-C и C # (Mac и Windows). Поддерживать их синхронизацию, внедрять богатый пользовательский интерфейс и тестировать QA было непросто. Качество взаимодействия с пользователем и ограниченный набор функций не позволяют нашим пользователям в полной мере пользоваться тем, что мы можем предложить. После некоторого исследования, периода исследований и множества обсуждений мы решили использовать единый стек:

Этот стек одинаков для Windows и Mac. В настоящее время у нас все еще есть устаревший собственный код, но мы быстро отказываемся от него. Подробнее об этом ниже.

TL; сводка DR

Мы уходим от нативного кода и переключаемся на локальные веб-представления Go +. Вот почему:

  1. Упростите: поддержание и синхронизация двух кодовых баз рабочего стола - это очень сложно, болезненно и дорого.
  2. Расширение возможностей: объединение технического стека позволяет всей команде вносить свой вклад и вводить новшества.
  3. Включить: новый стек позволяет нам легче и быстрее создавать новые функции кроссплатформенным способом, используя передовые технологии, сохраняя при этом доступ к собственным API.
  4. Приемлемые накладные расходы: хотя накладные расходы на ОЗУ, безусловно, есть, их можно и нужно минимизировать.

Это решение немного спорно из-за двух вещей: выбора использования Electron и того факта, что мы не остаемся в мире JavaScript и вместо этого вводим Go.

Электрон вызывает споры

Electron часто привлекает плохие комментарии к Hacker News, и это связано с очень большим использованием оперативной памяти. Приложение Slack является обычным приведенным примером. Проблема здесь более сложная, чем кажется. Electron - это оболочка вокруг Chromium, который является сердцем браузера Chrome. Другими словами, приложение отображает веб-представление в качестве основного. Веб-представления по умолчанию не так оптимизированы, как собственный код графического интерфейса, и это часто означает большие затраты на оперативную память, чем чисто собственные интерфейсы. Кроме того, сам Chromium загружает изрядную долю кода в память. Исходная стоимость окна Electron составляет около 40 МБ против ~ 4 МБ для собственного пользовательского интерфейса. Не очень хорошо ... но сколько оперативной памяти у вас на компьютере? Вы понимаете, что Chrome выделяет примерно такой же объем оперативной памяти, когда вы открываете новую пустую вкладку Chrome? Это не оправдание накладных расходов на память, но помогло мне дать некоторый контекст вокруг стоимости необработанных накладных расходов.

Проблема с приложением Slack

Люди, жалующиеся на использование оперативной памяти Electron, обычно ссылаются на такие приложения, как Slack, использующие 1 ГБ или более. Часто это происходит из-за пары проблем: архитектуры приложения и способа написания кода интерфейса.

На этапе расследования я понял, что лучше избегать использования модулей node.js, особенно нативных модулей. С ними было трудно работать (иногда странное поведение, трудно отлаживать, трудно тестировать) и часто требовалось много памяти. Вторая часть - это стоимость пользовательского интерфейса, загрузите веб-приложение в свой браузер и посмотрите, как использование памяти зашкаливает при загрузке картинок, гифок, звуков и большого количества данных. Некоторые приложения лучше других, и VSCode является хорошим примером приложения на основе Electron с очень разумным объемом памяти. Тем не менее, это правда, что большинство разработчиков интерфейсов не проверяют и не отслеживают использование памяти своими приложениями.

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

Оперативная память предназначена для использования, перестаньте дешеветь, пытаясь сохранить ее бесплатно - Лорен Мэтту

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

Веб-интерфейс: расширяйте возможности команды, делитесь знаниями

Что касается минусов, мы увидели небольшое увеличение использования ОЗУ, но как насчет преимуществ использования графического интерфейса на основе веб-интерфейса?

Основным преимуществом, очевидно, было то, что пользовательский интерфейс разработали только один раз и использовали его везде. Но это еще не все. Это решение также расширяет возможности большей части команды: все наши фронтенд-разработчики могут стать разработчиками настольных приложений. Им, безусловно, нужно понимать разницу между сетевым и локальным (техническими и поведенческими), но им не нужно изучать Какао или WPF. Также современные веб-API, такие как Web MIDI и Web Bluetooth, доступны через кроссплатформенный API в Chromium, если мы решим пойти по этому пути. Добавление новых функций пользовательского интерфейса теперь происходит намного быстрее, чем раньше (даже для наших талантливых инженеров).

Веб-фреймворк

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

Разделение проблем

Еще один интересный аспект нашего подхода заключается в том, что наша логика не живет в Electron, это обычное дело для приложений, которые реализуют логику, поэтому она выполняется в процессе N ode.js. Мы решили этого не делать и вместо этого запускаем процесс в собственном коде Go +. Интерфейс и основная служба общаются через gRPC. Такое проектное решение гарантирует, что разделение проблем действительно выполняется. Другими словами, мы реализуем ту же архитектуру, которую очень хорошо знаем и используем везде: клиент / сервер. Разница в том, что графический интерфейс взаимодействует не с веб-API, а с локальным сервером (который при необходимости выполняет проксирование некоторых вызовов и обрабатывает состояния онлайн / офлайн). Хотя это может показаться чрезмерно продуманным решением, мы планируем, чтобы другие приложения использовали наши услуги, и наличие локального API - это огромная победа. Мы рассматриваем графический интерфейс приложения как одного из потенциальных клиентов в неисключительных отношениях. Мы можем представить, что завтра другие приложения, плагины или цифровые аудио рабочие станции захотят взаимодействовать с нашим сервисом в стандартном, документированном и кроссплатформенном интерфейсе. Такое разделение проблем и соображений дизайна позволило бы это сделать.

Единая кодовая база с использованием Go

Мы потратили много лет на собственные приложения, и некоторые детали были реализованы по мере того, как мы обнаружили пограничные проблемы, связанные с расширенными функциями. Перенести этот код на Go нетривиально, и мы не хотели блокировать порт для отправки кода. Вот почему у нас все еще есть гибридная «основная» архитектура с собственным кодом + Go:

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

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

Тяжелая работа остается в Go и была перенесена из нативного кода. Простота Go, собственный параллелизм и возможность тестирования придали нам больше уверенности, уменьшили количество ошибок и дали возможность всей команде разработчиков присоединиться к веселью. Богатая экосистема Go также дает нам доступ к множеству интересных библиотек для будущих функций. Obj-C, Swift и C # - отличные языки, но они не являются частью наших основных языков. Я действительно рассматривал возможность использования C # / Xamarin для создания единого кроссплатформенного приложения. Но нам потребовалась бы специализированная и изолированная команда, и мы не смогли бы использовать столько наших знаний и опыта команды.

Заключение

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

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