Егор Долгов
Егор Долгов
За все время: 157 просмотров, 42 посетителя.
За последние 30 дней: 139 просмотров, 37 посетителей.

Анонс Dart 2.12

Согласованные нулевые типы (Sound null safety) и Dart FFI в стабильной версии!

Мы с радостью представляем вам Dart 2.12, обладающий стабильными версиями согласованных нулевых типов и Dart FFI. Null safety — наша последняя основная функция для повышения производительности, которая помогает избежать появления нулевых ошибок, класса ошибок, которые зачастую сложно обнаружить, как подробно описано в этом видео-введении. FFI — это механизм взаимодействия, позволяющий вызвать существующий код, написанный на языке программирования C, к примеру, вызвать API Win32.
Версия Dart 2.12 доступна уже сейчас!

Перевод статьи - Announcing Dart 2.12 https://medium.com/dartlang/announcing-dart-2-12-499a6e689c87
Автор оригинальной статьи — Michael Thomsen

Уникальные возможности платформы Dart

Прежде, чем мы подробнее рассмотрим согласованные нулевые типы и FFI, нужно разобраться с тем, как они вписываются в наши цели и задачи самой платформы Dart. Многие языки программирования имеют схожие возможности. К примеру, множество языков поддерживают объектно-ориентированное программирование или запуск в сети Интернет. Что действительно разделяет эти языки, так это уникальный набор этих самых возможностей.

Уникальные возможности Dart разделяются на три части:

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

Согласованные нулевые типы

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

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

Не нулабильный тип по умолчанию: фундаментальное изменение в системе типов

Основная проблема до нулевых типов заключалась в том, что вы не могли отличить код, от которого ожидается передача null, и код, который не работал с нулевыми значениями. Несколько месяцев назад мы обнаружили ошибку на главном канале Flutter, из-за которой различные команды инструмента Flutter вылетали на определенных машинных конфигурациях с ошибкой null: The method '>=' was called on null. Основная проблема заключалась в следующем коде:

Заметили ошибку? Поскольку version может быть null, то и major и minor также могут быть нулевыми. Вот так вот, в отдельном коде, этот баг легко заметить, однако, на практике, такие ошибки очень часто проскакивают даже со строгим процессом проверки кода, подобным тому, который используется в репозитории Flutter. При нулевых типах, статический анализ немедленно решает эту проблему. (Попробуйте в DartPad).

Скриншот вывода анализа в IDE

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

Работа с ненулабильными типами по умолчанию

После включения null safety основы деклараций переменных меняются, поскольку типы по умолчанию не допускают значения NULL:

Если вы хотите создать переменную, которая может содержать либо значение, либо null, то вы можете сделать это непосредственно в декларации переменной, добавив суффикс ? к типу:

Реализация нулевых типов является надежной, обладает богатым статическим анализом потока, упрощающим работу с типами, допускающими значение NULL. Например, после проверки на null Dart меняет тип локальной переменной с nullable на non-nullable:

Также мы добавили новое ключевое слово required. Когда заданный параметр помечается как required (что весьма часто случается в API-виджетах Flutter), а вызывающий не указывает аргумент, возникает ошибка анализа:

Постепенный переход к согласованным нулевым типам

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

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

Пока что новые пакеты и приложения, созданные с dart create и flutter create, не поддерживают согласованные нулевые типы. Мы надеемся исправить это в будущем, когда большая часть экосистемы уже мигрирует. Вы можете без проблем активировать нулевые типы в новых пакетах и приложениях при помощи dart migrate.

Статус перехода к согласованным нулевым типам в экосистеме Dart

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

Мы уже опубликовали версии с нулевыми типами сотни пакетов, предоставленные командами Dart, Flutter, Firebase и Material. Также мы получили большую поддержу от экосистем Dart и Flutter, так что в pub.dev теперь лежит более тысячи пакетов с поддержкой null safety. Первыми мигрировали наиболее популярные пакеты: 98% из топ-100 наиболее популярных пакетов, 78% от топ-250 и 57% из топ-500 уже поддерживают нулевые типы. Анализ показал, что большинство пакетов в pub.dev уже разблокированы и могут начать миграцию.

Преимущества полного использования null safety

Как только вы полностью мигрируете, нулевые типы становятся согласованными. Это значит, что Dart на все 100% уверен, что выражения неравного нулю типа не могут быть null. Когда Dart анализирует код и определяет, что переменная не допускает значения ноль, эта переменная всегда не допускает значения ноль. Dart имеет такую же нулевую безопасность, что и Swift.

Согласованность нулевых типов Dart имеет еще одно положительное свойство: теперь ваши программы могут быть меньше и быстрее. Поскольку Dart убеждается в том, что не нулевые переменные никогда не равны нулю, Dart оптимизируется. К примеру, компилятор Dart AOT может давать меньший и более быстрый нативный код, поскольку исчезает потребность проверки переменной на Null.

FFI для интеграции Dart с библиотеками языка C

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

Передача структур по значению

Структуры могут передаваться как по ссылке, так и по значению в коде C. Ранее FFI поддерживал передачу только по ссылке, но начиная с Dart 2.12, вы можете передавать структуры по значению. Вот небольшой пример двух функций C, которые передаются как по ссылке, так и по значению:

Вложенные структуры

C API часто используют вложенные структуры - структуры, которые сами содержат структуры, например, такие:

Начиная с Dart 2.12, вложенные структуры поддерживаются в FFI.

Изменения API

В рамках объявления FFI стабильным и для поддержки вышеперечисленных функций мы внесли несколько небольших изменений в API.

Исчезла возможность создания пустых структур (изменение #44622) — появляется объявление об устаревании. Вы можете использовать новый тип, Opaque, для репрезентации пустых структур. Такие функции dart:ffi, как sizeOf, elementAt и ref тперь требуют аргументы типа компиляции. Поскольку были добавлены новые удобные функции в package:ffi, в общих случаях не требуется дополнительных шаблонов для выделения и освобождения памяти:

Автоматическая генерация связей с FFI

Для покрытия большого API может потребоваться очень много времени для написания связей Dart, которые интегрируются с кодом C. Чтобы уменьшить эту нагрузку, мы создали генератор связей для автоматического создания оболочек FFI из файлов заголовков C. Вы можете попробовать: package:ffigen.

Направление FFI

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

Примеры использования FFI

Мы уже нашли много интересных применений Dart FFI для интеграции со многими API на языке C. Вот несколько примеров:

Что ожидает язык Dart в будущем?

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

Псевдонимы типов (#65): возможность создания псевдонимы типов к нефункционирующим типам. К примеру, вы можете создать typedef и использовать его как тип переменной:

Оператор тройного сдвига (#120): добавление нового, полностью переопределяемого оператора >>> для выполнения беззнакового битового сдвига целых чисел.

Аннотации общих метаданных (#1297): расширение аннотаций метаданных для поддержки аннотаций, содержащих аргументы типа.

Статическое метапрограммирование (#1482): поддержка статического метапрограммирования — программы Dart, которые создают новый исходный код Dart во время компиляции, аналогично макросам Rust и Swift Function builders. Эта функция все еще находится на ранней стадии изучения, но мы думаем, что она сможет позволить использовать варианты, которые полагаются на генерацию кода.

Dart 2.12 уже доступен!

Dart 2.12 с согласованными нулевыми типами и стабильным FFI уже доступен в SDK Dart 2.12 и Flutter 2.0. Также вы можете просмотреть вопросы по null safety для Dart и для Flutter. Если вы обнаружите еще какие-либо проблемы, пожалуйста, сообщите сюда.

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

Также вы можете оставить рецензию на использование как согласованных нулевых типов, так и FFI в твиттере @dart_lang

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