Релиз Dart 2.10: на шаг ближе к null-safety

Автор оригинала: Michael Thomsen, Kevin Moore
  • Перевод

image<img src="https://habrastorage.org/webt/bx/6z/zo/bx6zzobmc1fbzqkkzocurdk7gsg.jpeg" />


Команда языка Dart постепенно приближается к одному из самых мажорных релизов — null-safety. Эта фича есть у многих лидеров рынка, включая Kotlin и TypeScript. По понятным причинам этот релиз нельзя сделать в виде рубильника: одним днём и простым апдейтом. Набравшее скорость сообщество, выпустившее огромное количество пакетов, уже не сможет перейти на мажорную версию по щелчку пальцев. Поэтому процесс этот поступательный и не такой быстрый, как хотелось бы. Тем не менее сомневаться в том, что уже довольно скоро язык станет значительно лучше и удобнее, не приходится!


Мы в Wrike не смогли обойти стороной обновление релиз Dart 2.10 и переводим статью из официального блога Dartlang.


Новый, унифицированный dart для всех ключевых задач. А также апдейт по таймлайну null-safety и принципах миграции.


Авторы: Майкл Томсен и Кевин Мур


Сегодня мы анонсируем новый Dart, версия 2.10 (two-dot-ten). В этом релизе представлен новый унифицированный Dart: единый инструмент для всех возможных задач разработчика, таких как создание проектов, анализ и форматирование кода, тестирование и компиляция приложений. У нас есть обновленная информация об этапах работ по null-safety, а также принципы миграции существующего кода.


Новый унифицированный инструмент разработчика Dart


Dart составляет основу Flutter SDK: он не только предоставляет язык и среду выполнения, которые используются в приложениях Flutter, но и поддерживает многие основные задачи разработчика, такие как форматирование, анализ и тестирование кода. Однако, в то время как Flutter всегда имел один универсальный инструмент разработчика (команда flutter), у Dart исторически было много небольших инструментов (например, dartfmt и dartanalyzer). Dart 2.10 обзавелся новым, унифицированным инструментом разработчика dart, очень похожим на инструмент flutter. Этот новый инструмент поддерживает все основные задачи, такие как создание новых проектов и пакетов, анализ и форматирование кода, а также запуск, компиляцию и тестирование проектов. Чтобы использовать этот инструмент, просто выполните команду dart:



Flutter включает новый Dart во Flutter SDK. Начиная с версии Flutter 1.22 SDK, директория <flutter-sdk>/bin (которая чаще всего находится в PATH) содержит команды и flutter, и dart. Если вы занимаетесь разработкой как на Flutter, так и на Dart, вы получаете возможности обоих из одного пакета Flutter SDK без необходимости устанавливать что-либо еще.


Если хотите загрузить и установить другой Dart SDK (если вам требуется другая версия), убедитесь, что SDK инструмента dart, который вы хотите использовать по умолчанию, находится в начале переменной окружения PATH.

В следующих стабильных релизах мы планируем расширить функциональность инструмента dart и постепенно отказаться от меньших инструментов (dartdoc, dartfmt, dartanalyzer и т.п.). В 2021 году мы планируем выпустить Dart SDK, содержащий исключительно инструмент dart. Рекомендуем вам переключиться на новый инструмент при запуске команд Dart сейчас, будь то вручную в терминале или в системах сборки (CI), и сообщить нам, если чего-то не хватает или что-то работает не так, как должно.


О null-safety


Мы хорошо поработали с null-safety с тех пор, как несколько месяцев назад запустили первую техническую превью. В полной null-safety мы видим инструмент предотвращения трудно обнаруживаемых null-ошибок, а также дополнительный бонус к улучшению производительности. Если хотите узнать больше, рекомендуем нашу новую страницу Understanding null safety. Если предпочитаете короткое видео, посмотрите the null safety video с мероприятия Flutter Day, прошедшего несколько месяцев назад.


Когда null-safety будет готова к использованию? Вот наш прогноз:


  1. Работа Flutter с техническим превью 2: Мы успешно перенесли большую часть Flutter. Ожидаем, что скоро — вероятно, в течение следующего месяца — среда Flutter будет полностью перенесена, и, таким образом, мы будем готовы к экспериментальному использованию Flutter. Вы сможете попробовать null-safety во Flutter и выполнить пробную миграцию ваших приложений и пакетов Flutter. Вам нужно будет использовать экспериментальный флаг. Не используйте экспериментальные функции в продакшне и не публикуйте перенесенные пакеты.


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


  3. Использование в продакшне stable: в зависимости от обратной связи на запуск бета-версии мы исправим все оставшиеся проблемы, а затем опубликуем их в stable. Трудно назвать конкретные сроки, но мы думаем о начале следующего года. Как только эта функция станет стабильной, мы надеемся на широкое внедрение null safety приложениями, опубликованными в сторах, и многими и пакетами, опубликованными в pub.dev в стабильных версиях.



Принципы перехода к null-safety


Мы хотели бы поделиться нашими главными принципами для миграции на null-safety.


Переходите, когда будете готовы


Null-safety — это фундаментальное изменение в системе Dart. Это меняет основы объявления переменных, потому что мы решили сделать переменные ненулевыми по умолчанию:



Такое фундаментальное изменение было бы разрушительным, если бы мы настаивали на принудительном переходе. Мы хотим, чтобы вы сами выбрали подходящее время, поэтому null-safety — это опциональная функция: вы можете использовать последние версии Dart и Flutter без необходимости включать null-safety. Вы даже можете иметь зависимость между пакетами с уже включенной null-safety и приложениями или пакетами, которые ее еще не подключили.


Переходите постепенно, по порядку


Мы настоятельно рекомендуем переносить код по порядку, начиная с “листьев” графа зависимостей. Например, если C зависит от B, который зависит от A, сначала перенесите в null-safety A, затем B, затем C. Этот порядок применяется независимо от того, являются ли A, B и C библиотеками, пакетами или приложениями.


Почему порядок так важен? Вы можете добиться некоторого успеха в переносе кода до миграции ваших зависимостей, но вы рискуете столкнуться с необходимостью повторной миграции, если ваши зависимости изменят свои API в процессе переноса. Мы предоставим инструменты, которые помогут вам узнать, какие из зависимостей были успешно перенесены. Если вы являетесь автором пакета, то, чтобы избежать риска нарушения API, подождите, пока все ваши зависимости не будут перенесены, прежде чем публиковать null-safe версию.


Используйте автоматизированные инструменты для снижения затрат на миграцию


Когда ваши зависимости готовы и вы решаете мигрировать, можете использовать наш инструмент миграции. Он работает, анализируя весь ваш существующий код, ищет, какие объявления могут быть не не допускающими null (они остаются без изменений), а какие должны допускать значение null (нужен маркер ? null в объявлении).


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



Получите полную выгоду при полном использовании


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


Дальнейшие действия


Новый инструмент разработчика dart доступен сегодня в SDK Dart 2.10 и в SDK Flutter 1.22. Если у вас уже есть Flutter SDK, вы можете получить Dart SDK с помощью команды dart, просто запустив flutter upgrade; это даст вам Flutter 1.22 SDK, в который встроен Dart 2.10. Рекомендуем вам немедленно переключиться на новый инструмент dart и связаться с нами, если что-то отсутствует или не работает должным образом.


Скоро у нас будет больше новостей о null-safety. Скорее всего, в течение следующего месяца, когда наши друзья в команде Flutter будут иметь фреймворк Flutter с поддержкой null-safety, готовый к экспериментам. Следите за обновлениями в блоге Flutter. А пока вы можете поэкспериментировать с null-safe кодом Dart с помощью DartPad с null-safety и узнать больше о дизайне функции в документации по null-safety.

Wrike
Делаем совместную работу проще

Комментарии 28

    +1
    Спасибо, там еще у angulardart было крупное событие наконец то вышла версия 6, будете рассказывать что она привнесла интересного?
      0
      Обязательно расскажем!
      0
      Что там с поддержкой WASM?
      На сколько удобно на Dart + Flutter писать полноценные сайты?
        +1

        По поводу второго: писать удобно, но это все ещё не production ready решение.

          +3

          1) Про WASM можно почитать тут https://github.com/dart-lang/sdk/issues/32894


          Long story short: over the last 3 months we have hosted an intern who worked on targeting WASM+GC. He got some preliminary results: managed to implement enough of a backend working to translate a simple merge-sort benchmark. Unfortunately internship time has just run out. We are interested in driving this further, but right now we have no concrete plans, things are in discussion.

          2) Сайты — пока Flutter for Web сыроват конечно. Можно послушать последний выпуск Flutter Dev подкаста, мы как раз об этом говорили https://soundcloud.com/flutterdevpodcast/20-flutter-for-web

            0
            Интересный подкаст. Не понял только момент, разработчики flutter хотят отказаться от dom? Альтернатива имеет какое-нибудь accessibility?
              0

              Не то чтобы хотят… Просто в canvas рендерить куда проще, Skia (движок рендеринга) куда удобнее отрисовывать. Да и canvas быстрее. Но все проблемы понятны, accesibility, css, миллион всего. Ждём что будет в релизе

          +1
          Скажите, верно ли, что использовать приложение, с null safety, невозможно до тех пор, пока все зависимости приложения не будут поддерживать null safety? Ведь с т.з. «листов» — приложение будет самым последним кандидатом на обновление, а начинать нужно с первых.
            +3

            На самом деле можно, просто игнорируя или заглушив ошибки там, где вы пока не готовы мигрировать

              0

              А есть какой-то пример, как это сделать практически? Я пытался перевести проект на null-safety, однако с флагом эксперимента проект падал на библиотеках, а без него — уже dart ругался на новые синтаксические конструкции. Если такая возможность есть, то хотелось бы уже начать ее использовать, постепенно переводя зависимости на ns.

          +2

          Настоящее null-safety это когда ключевого слова null вообще нет в языке. А вопросики и лишние правила по сборке это костыли, которые только усложняют, а не упрощают.

            +5
            Как вы себе представляете взимодействие например с БД у которой null есть? По-моему получится система типов с которой неудобно работать в реальной жизни.
            ИМХО вопросики-это не костыли а нормальный способ, едиснтвенное что по-хоршему по умолчанию тип должен быть not-nullable(как тут и сделано), в отличии от других языков где в угоду обратной совместимости сделали наоборот.
              0

              Ну тут да, один неправильный дизайн накладывается на другой неправильный дизайн. В БД тоже не должно быть null, по идее. Ну тут только чего, заменять null на нулевове значение соответствующего типа, как делатся со строковыми типами, кстати.

                0

                мне кажется, что поскольку системы программирования так или иначе относятся к моделированию объектов реального мира, то null и всё с ним связанное просто неизбежно — а есть ли такой человек? может быть и нет. а есть ли заказ? его тоже может не быть. зачем мне maybe или новый объект если мне всёравно придётся обрабатывать варианты действий для да и нет. это просто огород городить, мы что будем спорить с реальностью в плане того что что-то должно быть но его нет? это часть систем, и мне кажется лучше получить ошибку nre и правильно обработать её, чем иметь какую-то странную логику с новым несуществующим объектом от базы данных когда мне просто нужно знать есть там что-то или нет. а не-nullable простыми типами можно легко пользоваться для построения цепочек вычислений проверяемых компилятором, потому что компилятор не может и не должен проверять бизнес-логику с которой связана ошибка nre. откуда ему знать, что делать если в базе нет записи которая там должна быть? создать новую, остановить систему, послать емэйл с оповещением, это же часть процессов которые компилятор не может контролировать

                  0

                  В объектах реального мира null-а то как раз и не существует. Допустим, вы рассказываете кому-то про человека или заказ. И вам просто необходимо будет сослаться на конкретного человека, конкретный заказ (например, заказ #123) или группу (коллекцию) людей/заказов, например, вчерашние заказы, или не оплаченные заказы. Иначе вас просто не поймут. У вас не получится рассказать о никаком заказе, хоть какие-то свойства да должны быть.
                  Тоже самое и в системах программирования, по крайней мере в высокоуровневых, которые оперируют объектами, а не указателями на область памяти. Либо существует ссылка на конкретный объект, либо ни объекта ни ссылки не существует. Но нет варианта когда существует ссылка в никуда.
                  NPE ошибку получить не проще, потому что ошибка NPE она очень техническая, она относится к тоу как процессор исполняет инструкции, и меньше относится к бизнес-логике. Одно дело NPE, другое дело ошибка "Поля abc не существует", вторая более приближена к бизнес логике и проще понять что не так и где исправлять.
                  Ни в том ни в другом случае естественно компилятор не может проверять бизнес-логику. Вы для этого программу и пишете.

                    0

                    пожалуйста:
                    пользователь должен был ввести слово, но ввёл пустую строку — это ""
                    не удалось показать пользователю ввод — это null. явно разные ситуации
                    дай мне из базы пользователя с I'd 1234 — нет такого пользователя (null) — тут даже не знаю что придумать… пользователь есть, но зовут его никак? как это иначе выразить без null?
                    мне это очень помогает в работе, не знаю может я что-то не понимаю, но мне кажется странным эти танцы вокруг null

                      –1

                      Мне тоже кажутся странными все эти танцы вокруг null. По-моему нет null -> нет танцев и все хорошо.


                      не удалось показать пользователю ввод — это null. явно разные ситуации

                      Вы хотите показать пользователю null? Да он офигеет


                      нет такого пользователя (null) — тут даже не знаю что придумать…

                      Исключение, или Optional. Но не null.

                        0
                        дай мне из базы пользователя с I'd 1234 — нет такого пользователя (null) — тут даже не знаю что придумать…

                        Это же абсолютно типичная ситуация, и решение тоже стандартное, ничего придумывать не надо. Метод в духе get_by_id возвращает не "пользователя", а "пользователя или ошибку". В ошибке уже конкретизируется, что пошло не так: id не зарегистрирован/нет прав на операцию/etc.

                  0
                  А где сделали наоборот?
                  0
                  У вас есть ссылка X на значение в другой переменой Y. Переменная Y удаляется. Что должно быть в переменной X?
                    +1

                    Думаю что Maybe<T>

                      0

                      В языках с автоматическим управлением памятью, таких как Dart, такое невозможно, там нет контроля за удалением объектов. Единственный вариант, когда ссылка X может быть null если в программе прямо написано X = null. Слово null в самом языке это проблема nullability, а не вопросики.
                      Никто не спорит, что в С/С++ null нужен, там есть и указатели и адресная арифметика. Но это не значит что эту концепцию надо тащить в другие языки, в которых другие концепции управления памятью. В языках типа Dart, объектно-ориентированных, не может быть null даже по смыслу. Как это, ссылка есть а объекта нет? Это нонсенс. Если нет объекта значит не должно быть переменных в которых вроде должна быть ссылка на этот объект, его же нет. Ссылка не может быть null, это против концепции ссылки на объект. Указатель на область память, к которому можно прибавить или отнять что-то — может, а ссылка на объект — нет

                        0

                        а как тогда строить алгоритмы, мы же не знаем что там будет? вот пример — обращаетесь к серверу, он может вернуть что-то а может ничего не вернуть. а вы же пишете программу до её выполнения, поэтому пишите как надо работать с ответом сервера. а потом оказывается что он ничего не вернул. что делать?

                          0

                          ну как, допустим есть JsonObject, у него есть метод has(name) который возвращает true если у объекта есть такое поле и false если нет. А если поля нет, но его значение пытаются получить то будет выброшено исключение.
                          Строить алгоритмы, предполагая, что никто никогда не возвращает null наоборот проще, потому что ненадо дополнительных проверок на null, собственно.

                            0

                            а мне это кажется гораздо более сложным, потому что что-то проверять всёравно придётся, потому что с этими данными надо же что-то делать дальше, а не просто получили и всё. но тут усложняется всё гораздо — вместо стандартной проверки на null придётся изучать принципы работы каждого объекта, чтобы проверить что у него там пошло не так. поэтому мне кажется это здорово что есть null, всегда можно вернуть что-то или ничего, вместо -1 например, что гораздо менее очевидно и более подвержено ошибкам. ошибки nre очень легко ловить и исправлять, и на этапе внедрения от 99% из них можно избавиться без труда, а вот когда какой-то алгоритм начнёт выдавать раз в 10 лет неправильные цифры потому что умножил что-то на -1 пару раз вместо ошибки, вот это будет багбаунти

                              0

                              А где-то говорят, что магические значения в духе ваших "-1" лучше, чем null? Не видел такого, и считаю что null конечно лучше из этих двух вариантов. Но зачем ими ограничиваться? В простейшем случае нужно возвращать не "правильный объект или null", а "правильный объект или ошибку", вот и всё.

                                0
                                ну так в том то и дело что это не ошибка, а совершенно штатная и предусмотренная ситуация. пусть она в этом месте не даст ошибку, но даст в следующем — всё всёравно упрётся в какуюто проверку.
                                наверно это просто дело вкуса, кому что больше нравится

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

                  Самое читаемое