Путь разработчика от скептицизма к воодушевлению по поводу будущего не-OEM-виджетов и индивидуального мобильного дизайна

Предисловие

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

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

  • «Клиенты не хотят платить все эти деньги и в конечном итоге получают приложение, которое не кажется родным».
  • «Не придется ли вам продолжать играть в догонялки с Google и Apple, у которых есть сотни умных людей, создающих новый интерфейс?»
  • «Мы хотим создавать быстро, но не можем идти на компромисс в отношении качества пользовательского интерфейса или производительности»
  • «Разработка унифицированного пользовательского интерфейса для обоих одновременно приведет к наименьшему общему знаменателю»

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

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

Чего хотят люди?

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

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

Чтобы понять суть продуктов, которые больше всего соответствуют потребностям их клиентов, давайте рассмотрим некоторые популярные и редакционные обзоры и награды за популярные приложения прошлых лет. Например, награды MWC Glomo Awards, Лучшие приложения года по версии TIME и раздел Мобильные приложения Webby Awards с их наградами People’s Voice, выбранными народным голосованием.

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

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

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

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

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

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

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

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

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

Вернемся к теме того, как это стремление связано с использованием или неиспользованием OEM-виджетов пользовательского интерфейса. Эта цель воплотилась в следующих принципах дизайна пользовательского интерфейса для Flutter:

1. Декларативный API

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

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

2. Модульность

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

Те же компоненты построения пользовательского интерфейса использовались командой Flutter для создания виджетов пользовательского интерфейса более высокого уровня, таких как виджеты Material Design. И эти компоненты разработаны разработчиками, чтобы их можно было расходовать, заменять и настраивать на каждом уровне. Другими словами, мы объединили «скины», которые имеют высокую точность воспроизведения, но не обладают особой привилегией. И при их создании мы создали набор инструментов, который упрощает создание любого стиля пользовательского интерфейса и виджета.

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

3. Предсказуемая последовательность

Заказчик всегда прав. Другими словами, если создатель приложения, эксперт в предметной области проблемы, которую он / она пытается решить, уже определился с внешним видом решения, тогда это решение является последовательным, предсказуемым и именно то, что разработчик и его пользователи должны получить. . И это должно быть верно независимо от версий совместимых библиотек, независимо от платформы, независимо от версий ОС, независимо от оформления телефона производителем (если разработчик не хочет, чтобы они были другими).

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

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

4. Не удивляйте пользователя.

Предыдущий раздел можно назвать «не удивляй разработчика». Хотя это так же важно, как и «не удивлять пользователей».

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

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

5. Плавные движения.

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

Как туда добраться

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

[Хорошая статья от Wm с описанием категоризации различных подходов]

Подход 1 - веб-технологии

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

Подход 2 - собственная упаковка виджетов

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

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

Подход 3 - рендеринг полного стека

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

Внизу, для прочной согласованности, проверенной на практике, Flutter начал с Skia, очень зрелого графического движка, используемого для рендеринга низкоуровневой графики Chrome, Firefox и Android. Благодаря прямому рендерингу с помощью инструкций OpenGL или Vulkan GPU, это гарантирует, что любой пользовательский интерфейс, созданный платформой поверх него, будет выглядеть предсказуемым и согласованным в различных средах выполнения.

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

И поскольку этот набор инструментов написан на Dart, который не только выразителен, но и полностью компилируется в код ARM, его характеристики производительности соответствуют приложениям, созданным на OEM SDK.

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

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

Затем, используя этот API-интерфейс для создания пользовательского интерфейса, мы создали набор богатых виджетов Material Design и Cupertino (iOS), включающий батареи, чтобы ускорить работу разработчиков, не ставя под угрозу их будущую способность углубляться и настраивать.

Мы также позаботились о том, чтобы эти виджеты (как включенные, так и созданные вами) легко соответствовали соглашениям платформы. Например, в произвольном порядке:

  • Прокрутка и чрезмерная прокрутка имеют различные жестко смоделированные физические симуляции между Android и iOS.
  • Компоненты, такие как панели навигации приложения (с оболочкой или без оболочки) по умолчанию соответствуют выравниванию текста, отступам и т. Д. ОС.
  • Кривые анимации переходов страниц, направления, продолжительность, изменения непрозрачности и т. Д. Соответствуют ОС
  • Поведение, зависящее от платформы, например, смахивание по краю для возврата, касание строки состояния для прокрутки вверх на iOS и касание внешних диалогов, чтобы закрыть на Android, работают должным образом.

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

Последствия для дизайна

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

Скорость разработки

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

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

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

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

Тестируемость

Набор инструментов пользовательского интерфейса, созданный с помощью композиции, по своей природе более тестируемый. Семантическое тестирование пользовательского интерфейса всегда было огромной головной болью для разработчиков мобильных приложений, использующих различные механизмы, такие как EarlGrey, Espresso, UI Automator, KIF и т. Д. интеграционные тесты верхнего уровня, выполнение которых требует больших затрат времени и ресурсов, поскольку для них требуется полная среда выполнения приложения (что снова вызывает ужасное переключение контекста при разработке, управляемой тестами).

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

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

Контроль разработчика

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

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

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

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

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

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

Разделение окружающей среды

Flutter отделяет инструментарий пользовательского интерфейса от ОС.

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

Материальный дизайн может быть реализован с такой же точностью в ранней бета-версии iOS 11, как и в Nexus S 2010 года (выпущен за 4 года до создания Material Design!) На Android 4.1.2. Не то чтобы мы обязательно кого-то поощряли к этому.

Соответственно, мы можем не только вернуться на 7 лет назад и выпустить собственный внешний вид бета-версии iOS 11 на устройстве Android 2010 года, но и упростили создание любого пользовательского интерфейса, который мы могли бы сделать, до того, как будет выпущена сама iOS 11. Опять же, не то чтобы кто-то захотел сделать приложение, похожее на iOS, на Android, но мы надеялись использовать его как лакмусовую бумажку, чтобы убедиться, что легко создать любой пользовательский интерфейс, будь то стандартный или фирменный.

Заключение

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

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

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

Попробуйте и убедитесь сами на flutter.io и поделитесь с нами своими мыслями в нашем канале чата или на GitHub!