Полное руководство по звуковой нулевой безопасности во Flutter/Dart

Что такое Null Safety, зачем и как его использовать? На этот раз давайте углубимся в Sound Null Safety!

Прежде чем мы начнем, я хочу кое-что сказать!

Я не знаю, почему некоторые люди ненавидят Null Safety (это не ненужный шаблон или что-то в этом роде!), но эта статья может помочь изменить их мнение, поэтому, пожалуйста, если рядом с вами есть кто-то, кто так думает, отправьте эту статью и помогите им просветить !

Как говорят опытные программисты;

Только лохи пишут отстойный код!

Если мы готовы, тогда приступим!

Что такое звуковая нулевая безопасность?

Прежде всего!

Нуль не зло, но и не лучший друг

Избавление от null не является целью. В null нет ничего плохого.

Основная цель — предотвратить непредвиденные нулевые ситуации, которые приводят нас к проблемам! Мы просто берем нулевое значение под контроль!

Зачем нам это вообще нужно?

Ответ прост! Чтобы не совершить ошибку на миллиард долларов!

Что такое добротность?

Это жаргонное слово в анализе статического программирования.

По сути, гарантирует, что программа не может попасть в определенные недопустимые состояния.

Преимущества надежности

  • Выявление ошибок, связанных с типом, во время компиляции. (ошибки выполнения идут к черту!)
  • Более читаемый и поддерживаемый код.
  • Улучшенная компиляция AOT (Ahead of Time).
  • Мы можем лучше заявить о наших намерениях. Это приводит к API, которые являются самодокументируемыми и более простыми в использовании.
  • Компилятор мог бы оптимизировать наш код и дать нам более компактные и быстрые приложения.

Теперь давайте немного взглянем на архитектуру!

До нулевой безопасности все содержит Null, и это приводит к тому, что каждый тип поддержки по умолчанию имеет значение null, и в этом проблема!

Как видите, мы отсоединили Null и изолировали его от дерева ради нулевой безопасности! Таким образом, от Nullничего не будет зависеть. Сделав это, мы предотвратим любую нежелательную проблему с нулевым значением в нашем приложении.

Давайте теперь посмотрим, как Null Safety работает на практике!

String myString;
bool isEmpty(String string) => string.length == 0;
// Without null safety
// Crashes while user's is using the app!
isEmpty(myString);
// With null safety
// The app can't even be compiled!
isEmpty(myString);
// So that we will ensure that null case handled properly
// and that will make our moms proud of us!

Теперь это имеет смысл, верно?

Тогда давайте теперь посмотрим на Null Aware Operators!!

Операторы с нулевым значением

? — Я переменная типа union Я могу быть как определенной переменной, так и Null

Это означает: String = String и String? = Строка или NULL

Некоторые основные правила

  • Если мы не сообщим Dart, что это значение может быть нулевым, Dart будет считать, что оно не может быть нулевым!
// WTH, bro? don't you see I only accept String values. Why you still trying me to set null!
String text;
  • Если вы не укажете значение для переменной, допускающей значение NULL, значение по умолчанию будет null.
// I got it, bro! I'm null for now but you'll set me a value later
String? text;

! — Обещаю, никакого нуля я здесь не пропущу!

String? text;
String newText = text!; // you can't assign it to me! Because you and I, We're different worlds variables. If you want me to be with you, you have to get rid of your null habits!

!. — Если кого-то не будет, вечеринка будет отменена!

class User { Address? address; }
class Address {String? name; }
user!.address!.name!

?. — Если кого-то не хватает, вечеринка окончена!

class User { Address? address; }
class Address {String? name; }
User? user;
// the first one is equivalent to the second one!
// choose your side wisely!
final name = user?.address?.name;
final name = getNameOrNull();
String? getNameOrNull() {
  if (user == null) {
    return null;
  } else {
    if (user!.address == null) {
      return null;
    } else {
      if (user!.address!.name == null) {
        return null;
      } else {
        return user!.address!.name;
      }
    }
  }
}

?? — если Джек не пойдет на вечеринку, просто приведи кого-нибудь еще!

String? jack;
String yep = jack ?? 'someoneElse';

??= — Если ваш друг не хочет присоединиться к нам, позвоните вместо него ___!

String? yourFriend;
String kevin = 'kevin';
String martha = 'martha';
yourFriend ??= kevin;
yourFriend ??= martha;
print(yourFriend); // returns kevin
// because jack join the group and martha couldn't make it!

поздно — я опоздаю, чтобы вы могли начать вечеринку без меня. Я присоединюсь к вам позже!

late String ehe; // won't throw an error because it'll be initialized later
ehe = 'yuppi';

Примечание. Если вы объявляете переменную late и эта переменная считывается до того, как ей будет присвоено значение, возникает ошибка.

Локальные переменные — наиболее гибкий случай. Ненулевая локальная переменная не нуждается в инициализаторе. Это прекрасно:

// result will be act like, it has a late keyword!
int someMethod() {
    int result; 
    result = 5;
    return result;
}

required — Необязательный параметр, но также должен получить значение!

// throws an error
// because you say it's optional can be null but also it's nullable!
void method({String value}){}
// now it's better!
void method({required String value}){}

Мы также можем контролировать спреды, каскады, индексы и ключи!

// Null-aware spread operator
final newList = [...list, ...?list2];
// Null-aware cascade operator
receiver?..method();
receiver!..method();
// Null-aware index operator
receiver?[i];
receiver![i];
// Null-aware key operator
map['key']?.name;
map['key']!.name;

Анализ потока Dart!

Компилятор Dart достаточно умен, чтобы анализировать поток кода и достижимость. Итак, даже если вы используете return, break или throw; вообще проблем не будет!

Давайте рассмотрим простой пример шаг за шагом

// Compiler will warn you because you didn't return anything!!
int method(String? value) {
}
// This time warn you because value can be null but you don't expect a null value!
int method(String? value) {
  return value.length;
}
// Dart will understand the value won't be null because It's checked before using
// and won't warn you for length issue but this time will warn you for unhandled return statement!
int method(String? value) {
  if (value != null) return value.length; // ok
}
// and we are perfect!
int method(String? value) {
  if (value != null) return value.length;
  return 0;
}

Как видите, Null Safety не оставляет нам места для ошибок!

Это делает приложение намного надежнее и безопаснее!

Наконец

Вы можете сказать, почему вы не говорите о Never?

Тогда я скажу, что нам понадобится почти NEVER! Так зачем беспокоиться?

Кстати, если вы еще не перенесли свой проект, нажмите на следующую ссылку!



Спасибо Полу Алларду. он подготовил краткий справочник по синтаксису в DartPad. Вы тоже должны это проверить!



Также, очень рекомендую эту статью вам для осмысления теории!



Рекомендации

Вы можете рассматривать эту статью как упрощенную версию официальной!







Спасибо за чтение!

Я постарался создать максимально простые примеры. Надеюсь, вам понравится.

Если вам понравилась эта статья, нажмите кнопку 👏 (знали ли вы, что можете дойти до 50?)