Почему Flutter использует Dart, а не Kotlin или JavaScript

Привет! Меня зовут Артём Зайцев, я руководитель Flutter-отдела в Surf.
Я и многие мои коллеги вышли из мобильной разработки, где господствуют Kotlin и Swift. Это очень «сахарные» языки: лаконичные, красивые, с элегантными конструкциями. Переход от них к Dart вызывает боль: «Зачем мне этот похожий на JS язык с динамической типизацией, когда у меня был Kotlin?» — думал я при первой встрече.
При первом знакомстве Dart вызывает крайне противоречивые чувства у большинства мобильных разработчиков. Поэтому во время конференций и вебинаров мы постоянно слышим вопрос: «Почему Flutter использует именно Dart?». В статье я хочу дать ответ на этот вопрос.
Откуда взялся Dart
Однажды мой коллега сказал: «Откуда, блин, взялся этот Dart? Я реально ничего не слышал о нём до появления Flutter».
И многие тоже ничего не слышали. А ведь Dart существует уже давно: если верить Википедии, его разрабатывают с 2011 года. Изначально он планировался как замена JavaScript от Google. Dart имел динамическую типизацию, был очень похож на JS и… на нём никто не писал, кроме разве что Wrike — долгое время они были единственной компанией, использующей этот язык.
Основную известность Dart приобрёл благодаря кроссплатформенному фреймворку Flutter.
Какой язык мог бы быть у Flutter вместо Dart
Давайте немного поразмышляем: какой язык мог бы занять место Dart? В голову приходят несколько кандидатов, потому что они довольно популярны:
- Kotlin. Знакомый язык и де-факто стандарт для Android-разработчиков. Куча сахара и красота, буквально идеальный язык. Продукт JetBrains. Компилируемый.
- JavaScript. Обеспечил бы поток веб-разработчиков во Flutter. Негативно воспринимается многими мобильщиками. Интерпретируемый.
- Swift. Проприетарный язык Apple — кажется, вряд ли он подойдёт фреймворку от Google. Компилируемый.
- TypeScript. По сути это обертка над JS от Microsoft. Строгая типизация, но те же минусы, что у JS.
По моему субъективному мнению здесь можно выделить Kotlin — уж очень я его люблю. Но у него нет тех свойств, что смогли бы обеспечить:
- подгрузку кода в приложение на лету в режиме отладки;
- синтаксис, понятный для людей с любых платформ;
- быстрый сборщик мусора;
- принадлежность к Google;
- открытость кода и общение с командой напрямую.
Пройдёмся по этим пунктам подробнее.
Особенности Dart
Компиляция и выполнение кода на Dart
В целом методы компиляции можно разделить на три типа.
Компиляция в промежуточный код. Основана на концепции виртуальной машины (VM), которая представляет собой продвинутый интерпретатор, эмулирующий аппаратное обеспечение внутри программного обеспечения. Виртуальная машина упрощает портирование языка для новых аппаратных платформ. В таком случае язык ввода для VM зачастую представляет собой промежуточный код. Например, код на языке программирования (скажем, на Java) компилируется в промежуточный код (байт-код Java), а затем исполняется на VM (JVM).
Just-in-time (JIT) компиляция. JIT-компиляторы используют метод компиляции во время работы программы, «на лету». Они существенно ускоряют цикл разработки, но программа может притормаживать и выполняться медленнее. С JIT-компилятором она запускается медленнее, потому что перед выполнением кода ему нужно одновременно успеть проанализировать и скомпилировать его. Согласно исследованиям многие пользователи скорее всего откажутся пользоваться приложением, если на его запуск уходит больше пары секунд.
Ahead-of-time (AOT) компиляция. AOT-компиляторы замедляют цикл разработки — промежуток времени, через который можно выполнить программу после внесения в неё изменений, чтобы посмотреть результат изменений. Но в результате AOT-компиляции разработчик получает программу, которая работает более предсказуемо, без перерывов на анализ и компиляцию в рантайме. Ещё такие программы, запускаются быстрее, потому что они уже скомпилированы.
Казалось бы, причём здесь Dart? Его разработчики провели грандиозную работу над продвинутыми компиляторами и виртуальными машинами: движком V8 для JavaScript и Strongtalk для Smalltalk — для интерпретируемых языков, компилятором Hotspot для Java — для компилируемых языков. На основе полученного опыта они постарались сделать Dart необычайно гибким с точки зрения методов компиляции и выполнения.
В итоге Dart отлично подходит как для AOT-, так и для JIT-компиляции. Поддержка обоих методов компиляции обеспечивает значительное преимущество для Dart и в особенности для Flutter.
К JIT-компиляции обращаются при разработке и используют самый быстрый компилятор. Затем, когда приложение готово к выпуску, используют AOT-компиляцию. В результате, благодаря продвинутым инструментам и компиляторам, Dart берёт лучшее от двух миров: чрезвычайно быстрый цикл разработки, быстрое выполнение и запуск.
На этом гибкость Dart с точки зрения компиляции и выполнения не ограничивается. Так, Dart можно компилировать в JavaScript, если нужно выполнить программу в браузере. В итоге получается переиспользовать код для мобильного приложения в web и наоборот. Некоторым разработчикам удаётся переиспользовать целых 70% кода в мобильных и web-приложениях. Ещё Dart можно применять для разработки серверных приложений: для этого потребуется компилировать его в нативный код или в JavaScript и использовать с node.js.
И, наконец, для Dart существует отдельная виртуальная машина — DartVM — которая использует язык Dart в качестве промежуточного, по сути выступая в роли интерпретатора.Dart можно компилировать методами AOT или JIT, интерпретировать или компилировать в другие языки. Это даёт разработчику мега-фичу под названием Hot Reload. С ней можно практически мгновенно и без потери состояния подгрузить код в приложение в режиме отладки. Это невероятно ускоряет процесс разработки и позволяет избежать нудной пересборки приложения для просмотра каждого изменения. А в релизе программа получит высокую производительность благодаря AOT-компиляции.
Сбор мусора
Hot Reload — крутая фича, но её используют только разработчики в дебаг-режиме. В чём тогда выгода Dart для уже готового приложения? Ведь конечная цель — это удобство для пользователей.
Здесь вступает в игру другое полезное свойство языка — его сборщик мусора. Да, самим сборщиком сейчас мало кого удивишь. Но здесь есть свои особенности, благодаря которым Flutter обеспечивает быструю работу и 60 FPS. Это даёт разработчикам возможность создавать крутые мобильные приложения с быстрым и отзывчивым пользовательским интерфейсом и секси-анимациями. Отчасти именно поэтому Flutter стал кроссплатформой, которая смогла завоевать доверие разработчиков.
Давайте вспомним, как работает Flutter: всё в нём — виджеты. А виджеты — это по сути объекты. Их много, и они пересоздаются с огромной скоростью при каждом изменении кода. Поэтому здесь нужен не просто сборщик мусора, а суперсборщик мусора.
В Dart используется продвинутая схема сбора мусора и выделение памяти на основе поколений объектов. Она особенно быстро выделяет память для большого количества объектов с коротким жизненным циклом. Это идеально для реактивных пользовательских интерфейсов вроде Flutter, где неизменяемое дерево виджетов пересобирается для каждого кадра.Благодаря такому сборщику Flutter приятен для разработки пользовательских интерфейсов в декларативном стиле. Мы используем конструкторы, создавая объекты, и описываем с помощью них верстку. Причём сами виджеты достаточно легковесны (это тоже важно), и представляют собой лишь информацию для отрисовки. Самой отрисовкой занимаются уже другие слои.
Понятный синтаксис
Выше я говорил, что переход с Kotlin на Dart был болью. Да, это так. Но самое интересное в другом: хоть мне и не хватало «сахара», я мог писать на Dart в тот же день. Наш опыт показывает, что члены команды могут писать на Dart и работать с Flutter уже через пару недель, если они перешли из другого стека, и через три-четыре недели, если они совсем новички. Причём освоение синтаксиса занимало всего несколько дней.
Dart очень прост и максимально близок любому разработчику, знакомому с Java/C#/JavaScript. У него хорошая и читаемая документация, а также подробный тур по языку. Благодаря этому можно научиться писать на Flutter достаточно быстро.
Ну и конечно в синтаксис Dart привносит изменения сам Flutter. Несколько фич в языке появились именно благодаря фреймворку и коммуникации команд Dart и Flutter — все они работают внутри Google.
Dart — это Google
Собственно, это не последняя причина. Работать со своим языком лучше, чем использовать продукт другой компании. Как минимум из-за того, что имеется больше влияния на его развитие.
Открытый код
Dart — это опенсорс. Он популярен как внутри Google, так и за его пределами. В Google его используют для Ads, Flutter, Fuchsia и других проектов — сейчас он среди наиболее быстро развивающихся языков. За пределами компании в репозиторий Dart коммитит более 100 сторонних разработчиков.
Немалую роль в этой популярности сыграл сам Flutter. Но открытость кода даёт разработчикам возможность общаться с командой Dart напрямую, видеть его развитие и фичи, которые в нём планируются.
Заключение
Перечисленные причины конечно же субъективны, но основаны на том, как развивается Flutter и Dart. Истину знают только в Google.
Dart позволяет Flutter быть именно таким, какой он есть — крутым фреймворком для создания классных кроссплатформенных приложений. В Dart сложились вместе все факторы: он вполне современный и обладает всеми необходимыми свойствами, прост в освоении, принадлежит Google. Идеальный кандидат для кроссплатформенного фреймворка, который изменит мир.