Segurança nula no Dart

Olá, Habr! Apresento a sua atenção a tradução do artigo "Anunciando segurança nula sonora" por Filip Hracek com meus comentários:



Segurança nula - trabalho seguro com links vazios. Mais adiante no texto, por brevidade e devido à estabilidade do termo, será utilizado o nome em inglês null, null safety. E a tradução "segurança zero" sugere pensamentos completamente opostos.

som - neste contexto (segurança nula de som) pode ser traduzido como "confiável".

Se você tiver sugestões para melhorar a tradução ou encontrar erros - escreva um pessoal, nós tentaremos consertar.
Um passo importante veio para a equipe Dart com a apresentação de uma prévia técnica dos desenvolvimentos de segurança nula. A segurança nula evita toda uma classe de bugs que geralmente são difíceis de detectar e, como bônus, fornece uma série de melhorias de desempenho. No momento, lançamos uma prévia técnica preliminar e estamos aguardando seus comentários.



Neste artigo, revelaremos os planos da equipe do Dart para implantar segurança nula, bem como explicar o que está por trás do termo segurança nula de som e como essa abordagem difere de outras linguagens de programação.

A versão descrita foi apresentada em 10 de junho de 2020.

Por que segurança nula?



Dart é uma linguagem de tipo seguro. Isso significa que quando você obtém uma variável de algum tipo, o compilador pode garantir que ela pertence a ela. Mas a segurança de tipo por si só não garante que uma variável não seja nula.



Erros nulos são comuns. Uma pesquisa no GitHub encontra milhares de relatórios (problemas) causados ​​por valores nulos no código Dart, e ainda mais commits tentando resolver esses problemas.



Tente identificar o problema do link de anulação no exemplo a seguir:



void printLengths(List<File> files) {
  for (var file in files) {
    print(file.lengthSync());
  }
}


Esta função certamente falhará se chamada com um parâmetro zerado, mas há um segundo caso a ser considerado:



void main() {
  // Error case 1: passing a null to files.
  printLengths(null);
 
  // Error case 2: passing list of files, containing a null item.
  printLengths([File('filename1'), File('filename2'), null]);
}


Segurança nula corrige este problema:



imagem



com segurança nula, você pode confiar em seu código com mais confiança. Não haverá mais erros irritantes de acessar uma variável anulada em tempo de execução. Apenas erros estáticos em tempo de compilação.

Para ser completamente honesto, a implementação atual ainda deixa várias oportunidades para detectar erros nulos no momento da execução, mais sobre eles mais tarde.

Segurança nula de som (confiável)



A implementação de segurança nula do Dart é válida. Se o analisarmos usando o exemplo acima, significa que o compilador Dart tem 100% de certeza de que o array de arquivos e os elementos nele contidos não podem ser nulos. Quando o compilador Dart analisa seu código e determina que a variável não é nula, então esta variável sempre terá um valor: se você verificar seu código executável no depurador, verá que simplesmente não há possibilidade de zerar em tempo de execução. Existem implementações que não são "confiáveis" nas quais você ainda precisa executar verificações para a existência de um valor no tempo de execução. Ao contrário de outras linguagens, o Dart compartilha a confiabilidade da implementação com o Swift.

, , , null safety . Swift, Kotlin Dart. .
Esta implementação robusta de segurança nula no Dart tem outra consequência interessante: significa que seus programas podem ser menores e mais rápidos. Como o Dart realmente garante que as variáveis ​​nunca sejam anuladas, ele pode otimizar o resultado da compilação. Por exemplo, o compilador AOT pode gerar código nativo menor e mais rápido porque não precisa adicionar verificações de referências vazias.



Vimos alguns resultados preliminares muito promissores. Por exemplo, vimos uma melhoria de desempenho de 19% em um microbenchmark que emula padrões de renderização típicos na estrutura Flutter.



Princípios básicos



Antes de prosseguir com o projeto detalhado de segurança nula, a equipe Dart definiu três princípios básicos:



Não anulabilidade por padrão. / ** Isso geralmente pode ser visto como uma abreviatura para NNBD na documentação ** / Se você não informar explicitamente ao Dart que uma variável pode ser anulada, ele a considerará não anulável. Escolhemos isso como o padrão porque descobrimos que, na API, um valor diferente de zero é atualmente o mais comum. / ** Este é provavelmente um retrabalho da API Flutter atual ** / .



Aplicabilidade em fases... Entendemos que deve haver a possibilidade de uma transição gradual para a segurança nula, passo a passo. Na verdade, você precisa ter um código de segurança anulável e nulo no mesmo projeto. Para isso, planejamos fornecer ferramentas que ajudem na migração do código.



Confiabilidade total (som). Como mencionado acima, a segurança nula no Dart é segura. Depois de converter todo o seu projeto e suas dependências em segurança nula, você obtém todos os benefícios de confiabilidade.



Declarando variáveis ​​com segurança nula



A sintaxe básica é bastante simples. Abaixo está um exemplo de declaração de várias variáveis. Observe que variáveis ​​não anuláveis ​​são usadas por padrão, então elas têm a mesma aparência, mas seus valores não podem ser anulados.



// In null-safe Dart, none of these can ever be null.
var i = 42;
final b = Foo();
String m = '';


O Dart garantirá que você nunca atribua nulo a nenhuma das variáveis ​​acima. Se você tentar executar i = null mesmo mil linhas depois, obterá um erro de análise estática e linhas vermelhas onduladas - seu programa se recusará a compilar.



Se quiser que sua variável seja anulável, você pode usar '?' como isso:



// These are all nullable variables.
int? j = 1;  // Can be null later.
final Foo? c = getFoo();  // Maybe the function returns null.
String? n;  // Is null at first. Can be null at any later time, too


As variáveis ​​listadas acima se comportam exatamente da mesma forma que todas as variáveis ​​na versão atual do Dart.



'?' 'também pode ser usado em outros lugares:



// In function parameters.
void boogie(int? count) {
  // It's possible that count is null.
}
// In function return values.
Foo? getFoo() {
  // Can return null instead of Foo.
}
// Also: generics, typedefs, type checks, etc.
// And any combination of the above.


Mas, novamente, eu desejo que você quase nunca precise usar '?'. A grande maioria de suas variáveis ​​não será anulável.



Tornando mais fácil usar a segurança nula



A equipe Dart está trabalhando duro para tornar a segurança null o mais fácil de usar possível. Por exemplo, dê uma olhada neste código, que usa if para testar o valor nulo:



void honk(int? loudness) {
  if (loudness == null) {
    // No loudness specified, notify the developer
    // with maximum loudness.
    _playSound('error.wav', volume: 11);
    return;
  }
  // Loudness is non-null, let's just clamp it to acceptable levels.
  _playSound('honk.wav', volume: loudness.clamp(0, 11));
}


Observe que o Dart é inteligente o suficiente para perceber que o volume não pode ser nulo no momento em que passamos a instrução if. E então o Dart nos permite chamar o método clamp () sem dançar desnecessariamente com um pandeiro. Essa conveniência é fornecida pela chamada análise de fluxo: o analisador Dart examina seu código como se o estivesse executando, descobrindo automaticamente mais informações sobre seu código.

Flow analysis, Dart, , , . null safety, :
foo(dynamic str) {
  if (str is String) {
    // dynamic   length,   
    //      String
    print(str.length);  
  }
}


, Dart , null, :
int sign(int x) {
  // The result is non-nullable.
  int result;
  if (x >= 0) {
    result = 1;
  } else {
    result = -1;
  }
  // By this point, Dart knows the result cannot be null.
  return result;
}


- (, result = -1;), Dart , result — , .
A análise de fluxo funciona apenas dentro de funções. Se você tiver uma variável global ou campo de classe, o Dart não pode garantir que um valor será atribuído a ele. O Dart não pode modelar o fluxo de execução de todo o seu aplicativo. Por esse motivo, você pode usar a nova palavra-chave atrasada se souber que a variável será inicializada quando for acessada pela primeira vez, mas não pode inicializá-la quando for declarada.



class Goo {
  late Viscosity v;
 
  Goo(Material m) {
    v = m.computeViscosity();
  }
}


Observe que v não pode ser zerado, embora inicialmente seja irrelevante. Dart acredita que você não tentará ler v até que seja atribuído um valor diferente de zero e seu código seja compilado sem erros.

— .



, . , . Dart , , , , , Kotlin .



— Swift- , , force unwrap Dart.

void main() {
  String? t;
  print(t!.length);
}


( late ‘!’) .



late , - Dart. ‘required’ . ‘@required’, .
class Temp {
  String str;
  Temp({required this.str});
  
  //   
  Temp.alt({strAtr}) : this.str = strAtr;
}




A equipe Dart tem trabalhado por mais de um ano para trazer segurança nula para uma prévia técnica. Esta é a maior mudança de idioma desde o lançamento da segunda versão. No entanto, essa é uma mudança que não quebra a compatibilidade com versões anteriores. O código existente pode chamar o código com segurança nula e vice-versa. Mesmo após um lançamento completo, a segurança nula será uma opção adicional que você pode usar quando estiver pronto. Seu código existente continuará a funcionar inalterado.



As bibliotecas principais do Dart foram atualizadas recentemente com segurança nula. Como um exemplo ilustrativo de compatibilidade com versões anteriores, a substituição das bibliotecas centrais existentes ocorreu sem um único teste com falha e sem erros em aplicativos de teste executados em ambientes de teste Dart e Flutter. Até mesmo a atualização das bibliotecas principais para muitos dos clientes internos do Google ocorreu sem problemas. Planejamos redesenhar todos os nossos pacotes e aplicativos para usar segurança nula após o lançamento, esperamos que você faça o mesmo. Mas você pode fazer isso no seu próprio ritmo, lote por lote, aplicativo por aplicativo.

Estas palavras, sim para os desenvolvedores do Swift, especialmente a 3ª versão ...

Mas mesmo aqui nem tudo é tão otimista, os próprios desenvolvedores dizem que ao combinar código de segurança nulo e código "antigo" em um projeto, eles não podem garantir solidez sistemas de tipo.

Plano de ação adicional



Planejamos implementar a segurança nula gradualmente em três fases:



  1. Pré-visualização técnica. Foi lançado quando o artigo original foi publicado (06/10/2020) e está disponível no dev-branch. Vale a pena prestar atenção na seção "Comece agora". Ainda é muito instável e sujeito a alterações, por isso não recomendamos usá-lo em código de produção ainda. Mas adoraríamos ouvir de você e nos dar feedback!
  2. Versão beta. A segurança nula estará disponível no branch beta do Dart e não mais se esconderá atrás de uma bandeira experimental. A implementação ficará próxima da versão final esperada. Será possível começar a migrar seus pacotes e plug-ins para pub.dev, mas não é recomendado publicar essa mudança como uma versão estável ainda.
  3. Versão estável. A segurança nula estará disponível para todos. Você será solicitado a publicar seus pacotes e plug-ins atualizados como versões estáveis. Também vale a pena migrar seus aplicativos neste estágio.


Se tudo correr de acordo com o planejado, lançaremos uma versão estável do Dart com segurança nula até o final do ano. De tempos em tempos, adicionaremos ferramentas para ajudá-lo a se mover para a segurança nula. Entre eles:



  • Uma ferramenta de migração para ajudar a automatizar as várias etapas de atualização de pacotes e aplicativos existentes;
  • pub.dev, null safety;
  • 'pub outdated' , null safety.




A maneira mais rápida de testar a segurança nula hoje é com nullsafety.dartpad.dev - a versão do DartPad com segurança nula ativada. Abra a lista suspensa Aprenda com Snippets para encontrar uma série de tutoriais que cobrem a nova sintaxe e os fundamentos da segurança nula.



imagem



Você também pode experimentar segurança nula em pequenos aplicativos de console (ainda não atualizamos estruturas maiores como o Flutter). Primeiro, você precisa baixar o SDK do Dart do branch dev e, em seguida, pode baixar este exemplo de aplicativo de console . O arquivo README contém instruções para executar o aplicativo com o recurso experimental de segurança nula ativado. Os outros arquivos no exemplo fornecem configurações de execução que permitirão a depuração no VS Code e no Android Studio.



Você também pode ler a documentação (mais aparecerão no futuro):





UPD: Nos comentários, sugeri este link Compreendendo a segurança nula


Estamos muito entusiasmados em poder implementar a segurança nula no Dart. O manuseio confiável e seguro de links vazios se tornará a marca registrada do Dart para ajudá-lo a escrever o código mais confiável e produtivo. Esperamos que você reserve algum tempo para experimentar a versão atual do null safety e deixe seus comentários em nosso rastreador de bug. Tenha um bom código!

Obrigado por ler até o fim. A tradução demorou um pouco, mas esperamos que os comentários tenham sido úteis para o material e não tenha se tornado apenas uma tradução individual. Quero acrescentar que esse recurso é um passo à frente realmente útil para todo o ecossistema Flutter. Estou ansioso para usá-lo já em aplicativos ativos. Nesse ínterim, como se costuma dizer em língua estrangeira, fique atento!



All Articles