Entendendo o null safety
Tags: dart, flutter, beginners, braziliandevs
Published: 2021-10-12 15:31:42

Olá pra você que está chegando de paraquedas nesse artigo, ou está seguindo um link que eu provavelmente publiquei em alguma das minhas redes! Espero que esteja muito bem hidratado(a), por que nesse artigo vamos buscar entender de uma forma simplificada o null safety, que abalou muitos corações na atualização do flutter 2.0.

Este é um artigo beginner friendly, então já fiquem avisados que não há o que temer e depois desse artigo espero que vocês olhem para essa feature de uma maneira mais simpática, pois ela veio para te ajudar.

Antes de começarmos, sugiro que você abra o DartPad (https://dartpad.dev/) e vá testando códigos com e sem null safety pra você entender melhor e ver na prática as coisas acontecendo!

##O que é null

Antes de falar propriamente sobre o null safety, precisamos primeiramente entender o conceito de null:

Uma variável tem o valor null quando nenhum valor foi atribuído à ela, ou seja, é literalmente nada. Por exemplo:

Se eu inicializar uma variável sem passar um valor referente à ela:

`String nome;
print(nome);`

Em um ambiente sem o null safety habilitado poderemos ver que imprimimos 'null' no console, justamente por não termos atribuído nenhum valor aquela variável.

Assim, se quiséssemos tratar situações em que uma variável pode ser nula, poderíamos fazer da seguinte maneira:


![if(variavel == null){
print('não temos um valor para essa variável');
} else {
print(variavel);
}](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4yiscbum32iutn7eyoa.png)

Agora, se você for iniciante (como eu sou), você deve estar tendo alguma dificuldade em entender as implicações práticas disso, e é normal no início a gente não ter uma dimensão do que significa isso dentro de um sistema real, afinal, é só tratarmos como no exemplo acima que tá tudo certo né? Bom, na teoria sim, mas vou contar pra vocês que erros de null são os mais comuns em sistemas do mundo todo, são tão comuns que a primeira pessoa que criou o null, Tony Hoare, pediu publicamente desculpas por tê-lo criado e o chamou de "billion dollar mistake", o erro de um bilhão de dólares.

##Tempo de compilação vs Tempo de execução

Até aqui conseguimos definir o que é null e entender que variáveis com valores null são a causa de um dos bugs mais comuns em programas no mundo. 
Vamos agora entender a diferença entre tempo de compilação e tempo de execução no processo de desenvolvimento de software, pois isso foi um conceito crucial para que eu entendesse a importância e praticidade que null safety traz para os nossos programas.

Quando estamos escrevendo código em linguagens de alto nível, ou seja, que são mais próximas da linguagem humana e mais afastadas da linguagem de máquina (como por exemplo Java, JavaScript, Python e nosso querido Dart), necessitamos de um compilador, que é como se fosse um tradutor, um conversor que vai fazer com que a máquina o compreenda.

O tempo em que estamos escrevendo esse código podemos chamar de tempo de compilação, nesse tempo o computador pode reconhecer erros de sintaxe e semântica sem que seja necessária a execução do programa.

O tempo de execução é exatamente isso que o nome diz, é quando um programa entra em execução, e nesse estágio o programa consegue detectar comportamentos que durante o tempo de compilação não puderam ser previstos, podendo assim gerar erros que muitas vezes quebram o programa.

Sendo assim, eu posso escrever a seguinte função para definir o nome completo de um membro da família Martins:


![ String sobrenome = 'Martins';
  String nomeCompleto(String nome) {
    return nome + ' ' + sobrenome;
  } nomeCompleto(null)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pi2d9njocq9fo82q0k1.png)


Sem o null safety esse código compilaria, causando um erro somente em tempo de execução, porém quando habilitamos o null safety, já em tempo de compilação o computador nos avisa que um parâmetro do tipo null não pode ser atribuído a um parâmetro do tipo String, isso se deve ao fato de que com o null safety por padrão as variáveis nunca podem ter um valor null, evitando assim que nosso programa quebre.

##Null Safety

O nome já diz: segurança null. Essa feature chegou para fazer nossos códigos mais seguros e a prova de erros, e agora vamos entender o null safety de uma maneira que a gente poderá trabalhar com ou sem ele, assim não importa se você estiver vendo um tutorial ou artigo sobre dart e flutter que foi feito antes do null safety, você saberá exatamente o que fazer para adaptar o código para as versões mais atuais do flutter.


###Operador "?"
Por padrão, depois do null safety, todas as variáveis nunca poderão ser nulas, ou seja, elas são "non nullable". Mas aí vocês me perguntam: "mas Rafa, como fazemos então quando a gente QUER que aquela variável seja nula pelo menos durante um determinado momento do programa?" Isso é simples, basta sinalizar com um "?" logo após a tipagem dela, dessa maneira:


![final String? nome;](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5hxipfr9v4nl5h0ops6.png)

Esse padrão é muito utilizado na criação de classes:


![class Pessoa{
  Pessoa({required this.nome, required this.idade, 
  this.pet});
  final String nome;
  final String idade;
  final String? pet;
}](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwk1wpifuosa0axmnjb7.png)


Todas as pessoas tem um nome e idade, mas nem todo mundo tem um bichinho de estimação, assim eu sinalizei para o programa que o campo "pet" não é obrigatório, e coloquei a palavra reservada `required` para dizer que os campos "nome" e "idade" são obrigatórios na criação de uma variável do tipo Pessoa.

Ok, mas e se quiséssemos realizar operações com uma variável sem saber se ela é nula ou não?

Se escrevêssemos o seguinte código:


![void main(){
  int num1;
  int num2 = 10;
  int soma(int a, int b){
   return a +b;}
 print(soma(num1, num2));}](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64j3e0rm52zulci9an0p.png)

Com o null safety, em tempo de compilação já saberíamos que nosso código não está seguro e conseguiríamos consertar esse erro bem facilmente mesmo a variável `num1` podendo ser nula, da seguinte forma:

![void main(){
  int? num1;
  int num2 = 10;
  int soma(int a, int b){
    return a +b;}
 if(num1 != null){
  print(soma(num1, num2));}}](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eou9xg6bracnuicyvtb4.png)

E por incrível que pareça o Dart vai ficar feliz com esse código sim, pois ele é bem inteligente e já sabe que a função só será executada caso a variável `num1` não seja nula!

Também podemos utilizar o operador "??" para executarmos alguma ação caso algum valor seja nulo:

![int? x;
 int y = x ?? 0;
print(y);//0](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sunminudv11ba58ztgea.png)

###Operador "!"

Usamos esse operador quando temos certeza de que uma variável que pode ser nula tem um valor naquele momento do programa, permitindo assim que a gente execute funções e atribuições envolvendo aquela variável:


![  int banana = 10;
  int? abacaxi;
  if (banana > 0) {
    abacaxi = 2;}
  int frutas = banana + abacaxi!;
  print(frutas);](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zj2i571zvte700b3ntlf.png)

Sem o "!" o Dart iria reclamar, mas esse sinal é como se a gente falasse pra ele "fica sussa fiote, eu sei o que eu estou fazendo!", e ele confia na gente fácil assim! Só cuidado pra não vacilar e ele mandar uma de "eu avisei!"...

##Conclusão

Você chegou até aqui?! Que maravilha, estou muito feliz e espero que você tenha conseguido compreender melhor o null safety e escrever códigos mais confiáveis e seguros!

Existem várias outras situações que poderíamos nos deparar durante a criação dos nossos códigos com null safety e que eu não cobri nesse artigo, pelo fato de que iria ficar muito longo e cansativo, mas espero ter esclarecido o uso dos operadores, o porquê do null safety e como trabalhar com ele.

Hoje ouvi uma pessoa muito querida dizer num podcast que programar é como um super poder, eu achei a analogia fantástica, e é como se a cada coisa nova que aprendemos, adicionamos mais algo especial nesse super poder, algo que vai fazer a diferença pra alguém em contato com a tecnologia que criamos!

Vamos então salvar o dia com nossos super poderes :)

Happy coding!


*Esse artigo foi feito com muita ajuda das explicações do curso de Dart do Andrea Bizzotto na Udemy além de outras fontes diversas na internet. Pra quem entende inglês e quer um curso com explicações claras e projetinhos mão na massa, eu recomendo fortemente o curso do Andrea!