Егор Долгов
Егор Долгов
За все время: 350 просмотров, 106 посетителей.
За последние 30 дней: 97 просмотров, 21 посетитель.

Представляем Dart 2.13

Новые функции псевдонимов (алиасов) типов, улучшенный Dart FFI.

Перевод статьи Announcing Dart 2.13
Автор оригинальной статьи: Michael Thomsen

Представляем обновление Dart 2.13 — версия, в которой появились псевдонимы (алиасы) типов — одна из наиболее запрашиваемых функций языка. Также улучшен Dart FFI, повышена производительность, добавлены Docker Official Images. Кроме того, в этой статье вы можете узнать последние сведения о поддержке нулевых типов, объявленной в Dart 2.12, новости о поддержке Docker и Google Cloud для бэкендов Dart, а также о том, что будет вас ждать в последующих релизах.

Обновление null safety

В мартовском релизе Dart 2.12 мы запустили согласованные нулевые типы — одну из самых важных функций для улучшения производительности, созданную для того, чтобы помочь избежать ошибок на null (заметить их самостоятельно зачастую очень сложно). Вместе с релизом мы призвали разработчиков пакетов на pub.dev к миграции к согласованным нулевым типам.

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

Теперь, когда столько пакетов поддерживают согласованные нулевые типы, вы и сами можете мигрировать свое приложение к их поддержке. Первым шагом станет проверка зависимостей своего приложения, используя dart pub outdated. Подробнее об этом процессе вы можете узнать в этом руководстве. Были изменены шаблоны dart create и flutter create, и теперь они используют согласованные нулевые типы по умолчанию при создании новых приложений и пакетов.

Псевдонимы (алиасы) типов

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

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

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

Хорошим примером может послужить работа с JSON (благодарим за этот пример пользователя GitHub Levi-Lesches). Мы можем определить новый псевдоним типа Json, который описывает документ JSON как карту из ключей String для любого значения (используя тип dynamic). Затем мы используем этот псевдоним типа Json при определении конструктора fromJson и геттера json.

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

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

Если мы попытаемся использовать несовпадающие типы, появится ошибка анализа:

Вы можете использовать псевдонимы типов даже при переименовании классов в публичных библиотеках. Допустим, в публичной библиотеке у вас есть уже существующий класс PoorlyNamedClass, и вы хотите переименовать его в BetterNamedClass. Если вы просто переименуете этот класс, пользователи вашего API внезапно начнут получать ошибки компиляции. Вместо этого вы можете переименовать класс, затем определить новый псевдоним типов для старого названия класса, и добавить аннотацию @Deprecated для старого имени. Все использования PoorlyNamedClass будут выдавать предупреждение при работе, но будут продолжать компилироваться и не прекратят работу, что даст пользователям время для обновления своего кода.

Вот как можно имплементировать BetterNamedClass и исключить PoorlyNamedClass (в файле под названием mylibrary.dart):

А вот что случится, если кто-то попробует использовать PoorlyNamedClass:

Чтобы включить функцию псевдонимов типов, установите нижнее ограничение Dart SDK в своей публичной спецификации как минимум на 2.13 (в файле pubspec.yaml):

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

Изменения в Dart 2.13 FFI

В Dart FFI, наш механизм взаимодействия для вызова кода C, также появилось несколько новых функций. Например, появилась поддержка структур со встроенными массивами (#35763):

Теперь вы можете напрямую обернуть это в Dart, указав тип элемента с аргументом типа для Array:

Также FFI теперь поддерживает пакетированные структуры (#38158). Обычно структуры размещаются в памяти так, чтобы их члены попадали в границы адресов, к которым проще получить доступ для ЦП. В упакованных структурах некоторые из этих отступлений опускаются, чтобы снизить общее потребление памяти, часто в зависимости от платформы. С новой аннотацией вы можете легко указать отступ. Например, следующий код создает структуру с 4-байтовым выравниванием, когда она находится в памяти:

Улучшения производительности Dart 2.13

Мы продолжаем работать над уменьшением размера приложения и объема памяти, занимаемой кодом Dart. В больших приложениях Flutter внутренние структуры, представляющие метаданные AOT-скомпилированной программы Dart, могут занимать много памяти. Большая часть этих метаданных присутствует для включения таких функций, как горячая перезагрузка, интерактивная отладка и форматирование удобочитаемых трассировок стека — функций, которые никогда не используются в развернутых приложениях. В прошлом году мы реструктурировали встроенное время выполнения Dart, чтобы максимально устранить эту накладку. Некоторые из этих улучшений применимы ко всем приложениям Flutter, созданным в режиме релиза, но некоторые требуют, чтобы вы отказались от удобочитаемых трассировок стека путем разделения отладочной информации из приложений, скомпилированных AOT, с помощью флага --split-debug-info.

Dart 2.13 включает несколько изменений, значительно уменьшающих расход памяти, занятой метаданными программы при использовании --split-debug-info. Возьмем Flutter Gallery app в качестве примера. У релиза для Андроид APK занимает 112.4 MB с информацией об исправлении ошибок и 106.7 MB без нее (разница примерно 5%). Этот APK содержит множество активов (assets). Если посмотреть только на метаданные кода внутри APK: они были уменьшены с 5,7 МБ в Dart 2.12 и до всего 3,7 МБ в Dart 2.13 (сокращение на 35%).

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

Официальная поддержка Docker и Dart в Google Cloud

Теперь Dart доступен как Docker Official Images. В то время как Dart предоставляет образы Docker в течение многих лет, эти новые образы Dart тестируются и проверяются Docker на предмет соответствия лучшим практикам. Они также поддерживают предварительную компиляцию, которая может значительно уменьшить размер построенных контейнеров и повысить скорость развертывания в контейнерных средах, таких как Cloud Run.

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

В целом, использование Dart для серверных частей приложений Flutter особенно хорошо подходит для простоты и масштабируемости управляемой бессерверной платформы Google Cloud Run. Это включает масштабирование до нуля (scale-to-zero), что означает, что вы не несете никаких затрат, если серверная часть не обрабатывает какие-либо запросы. Мы работаем с командой Google Cloud, чтобы предоставить Functions Framework (функциональный фреймворк) для Dart, коллекцию пакетов, инструментов и примеров, которые упрощают написание функций Dart для развертывания вместо полных серверов для обработки HTTP-запросов и CloudEvents.

Ознакомьтесь с нашей документацией по Google Cloud, чтобы начать работу.

Несколько слов о том, что будет дальше

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

Одна из областей, над которой мы работаем, - это новый набор canonical lints для Dart и Flutter. Lints — это мощный способ настройки статистического анализа Dart. Однако с сотнями возможных линтов, которые можно включить или выключить, может быть сложно решить, что выбрать. В настоящее время мы работаем над определением двух канонических наборов линтов, которые мы будем применять по умолчанию в проектах Dart и Flutter. Мы ожидаем, что они будут включены по умолчанию в следующем стабильном выпуске. Если вам нужен предварительный просмотр, ознакомьтесь с двумя пакетами lints и flutter_lints.

Наконец, если вы используете глубокое связывание среды выполнения Dart VM, обратите внимание, что мы планируем отказаться от существующего механизма для этого. Мы заменим его более быстрой и гибкой моделью на основе Dart FFI (см. Проблему отслеживания #45451).

Dart 2.13 доступен уже сегодня

Dart 2.13, обладающий псевдонимами типов и улучшенным FFI, уже доступен в SDK Dart 2.13 и Flutter 2.2.

Если вы ждали, пока ваши зависимости перейдут к согласованным нулевым типам, советуем вам проверить это снова, используя dart pub outdated. Поскольку 93% из 500 самых популярных пакетов уже перенесены, есть большая вероятность, что вы имеете доступ к поддержке null safety. Мы также хотели бы выразить большую благодарность разработчикам, которые уже выполнили миграцию!

Подборка заметок