Seguridad nula en Dart

¡Hola, Habr! Presento a su atención la traducción del artículo "Anunciando una seguridad sólida y nula" de Filip Hracek con mis comentarios:



Seguridad nula - trabajo seguro con enlaces vacíos. Más adelante en el texto, por brevedad y debido a la estabilidad del término, se utilizará el nombre en inglés null, null safety. Y la traducción "seguridad cero" conduce a pensamientos completamente opuestos.

sonido - en este contexto (seguridad de sonido nulo) se puede traducir como "confiable".

Si tiene sugerencias para mejorar la traducción o encuentra errores, escríbalo personalmente, intentaremos solucionarlo.
Ha llegado un paso importante para el equipo de Dart con la presentación de un avance técnico de los desarrollos de seguridad nula. La seguridad nula evita toda una clase de errores que a menudo son difíciles de detectar y, como beneficio adicional, proporciona una serie de mejoras de rendimiento. Por el momento, hemos publicado una vista previa técnica preliminar y estamos esperando sus comentarios.



En este artículo, revelaremos los planes del equipo de Dart para implementar la seguridad nula, además de explicar qué se esconde detrás del término seguridad nula de sonido y en qué se diferencia este enfoque de otros lenguajes de programación.

La versión descrita se presentó el 10 de junio de 2020.

¿Para qué sirve la seguridad nula?



Dart es un lenguaje de tipo seguro. Esto significa que cuando obtiene una variable de algún tipo, el compilador puede garantizar que le pertenece. Pero la seguridad de tipos por sí sola no garantiza que una variable no sea nula.



Los errores nulos son comunes. Una búsqueda en GitHub encuentra miles de informes (problemas) causados ​​por valores nulos en el código de Dart, e incluso más confirmaciones que intentan resolver estos problemas.



Intente detectar el problema del enlace nulo en el siguiente ejemplo:



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


Esta función ciertamente fallará si se llama con un parámetro puesto a cero, pero hay un segundo caso a considerar:



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]);
}


La seguridad nula soluciona este problema:



imagen



con la seguridad nula, puede confiar en su código con más confianza. No habrá más errores molestos al acceder a una variable anulada en tiempo de ejecución. Solo errores estáticos en el momento de la compilación.

Para ser completamente honesto, la implementación actual todavía deja varias oportunidades para detectar errores nulos en el momento de la ejecución, más sobre ellos más adelante.

Seguridad nula de sonido (confiable)



La implementación de Dart de seguridad nula es sólida. Si lo analizamos usando el ejemplo anterior, significa que el compilador de Dart está 100% seguro de que la matriz de archivos y los elementos que contiene no pueden ser nulos. Cuando el compilador de Dart analiza su código y determina que una variable no es nula, esta variable siempre tendrá un valor: si verifica su código ejecutable en el depurador, verá que simplemente no hay posibilidad de poner a cero en tiempo de ejecución. Existen implementaciones no "confiables" en las que aún necesita realizar comprobaciones de la existencia de un valor en tiempo de ejecución. A diferencia de otros idiomas, Dart comparte la confiabilidad de la implementación con Swift.

, , , null safety . Swift, Kotlin Dart. .
Esta implementación robusta de seguridad nula en Dart tiene otra buena consecuencia: significa que sus programas pueden ser más pequeños y rápidos. Dado que Dart realmente se asegura de que las variables nunca se puedan anular, Dart puede optimizar el resultado de la compilación. Por ejemplo, el compilador AOT puede generar código nativo más pequeño y más rápido porque no necesita agregar comprobaciones para referencias vacías.



Hemos visto algunos resultados preliminares muy prometedores. Por ejemplo, vimos una mejora del rendimiento del 19% en un microbenchmark que emula los patrones de representación típicos en el marco de Flutter.



Principios básicos



Antes de continuar con el diseño detallado de seguridad nula, el equipo de Dart definió tres principios básicos:



No nulabilidad por defecto. / ** A menudo se ve como una abreviatura de NNBD en la documentación ** / Si no le dice explícitamente a Dart que una variable puede ser anulada, la considerará no anulable. Elegimos esto como el predeterminado porque descubrimos que en la API, un valor distinto de cero es, con mucho, el más común. / ** Esta es probablemente una reelaboración de la API Flutter actual ** / .



Aplicabilidad por fases... Entendemos que debería existir la posibilidad de una transición gradual a la seguridad nula paso a paso. De hecho, debe tener un código de seguridad nulo y anulable en el mismo proyecto. Para ello, planeamos proporcionar herramientas para ayudar con la migración de código.



Fiabilidad total (sonido). Como se mencionó anteriormente, la seguridad nula en Dart es segura. Una vez que convierta todo su proyecto y sus dependencias en seguridad nula, obtendrá todos los beneficios de confiabilidad.



Declaración de variables con seguridad nula



La sintaxis básica es bastante simple. A continuación se muestra un ejemplo de declaración de varias variables. Tenga en cuenta que las variables que no aceptan valores NULL se utilizan de forma predeterminada, por lo que tienen el mismo aspecto, pero su valor no se puede anular.



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


Dart se asegurará de que nunca asigne nulo a ninguna de las variables anteriores. Si intenta ejecutar i = null incluso mil líneas más tarde, obtendrá un error de análisis estático y líneas onduladas rojas: su programa se negará a compilar.



Si desea que su variable sea anulable, puede usar '?' Me gusta esto:



// 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


Las variables enumeradas anteriormente se comportan exactamente igual que todas las variables en la versión actual de Dart.



'?' 'también se puede utilizar en otros 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.


Pero de nuevo, desearía que casi nunca tuvieras que usar '?'. La gran mayoría de sus variables no admitirán nulos.



Facilitar el uso de seguridad nula



El equipo de Dart está trabajando duro para hacer que la seguridad nula sea lo más fácil de usar posible. Por ejemplo, eche un vistazo a este código, que usa if para probar 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));
}


Tenga en cuenta que Dart es lo suficientemente inteligente como para darse cuenta de que el volumen no puede ser nulo en el momento en que pasamos la declaración if. Y así Dart nos permite llamar al método clamp () sin bailar innecesariamente con una pandereta. Esta conveniencia es proporcionada por el llamado análisis de flujo: el analizador de Dart mira su código como si lo estuviera ejecutando, obteniendo automáticamente más información sobre su 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 — , .
El análisis de flujo solo funciona dentro de las funciones. Si tiene una variable global o un campo de clase, Dart no puede garantizar que se le asigne un valor. Dart no puede simular el flujo de ejecución de toda su aplicación. Por esta razón, puede usar la nueva palabra clave tardía si sabe que la variable se inicializará cuando se llame por primera vez, pero no puede inicializarla cuando se declare.



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


Tenga en cuenta que v no se puede poner a cero, aunque inicialmente es irrelevante. Dart piensa que no intentará leer v hasta que se le asigne un valor distinto de cero y su código se compile sin errores.

— .



, . , . 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;
}




El equipo de Dart ha estado trabajando durante más de un año para llevar la seguridad nula a una vista previa técnica. Este es el mayor cambio de idioma desde el lanzamiento de la segunda versión. Sin embargo, este es un cambio que no rompe la compatibilidad con versiones anteriores. El código existente puede llamar al código con seguridad nula y viceversa. Incluso después de un lanzamiento completo, la seguridad nula será una opción adicional que puede usar cuando esté listo. Su código existente seguirá funcionando sin cambios.



Las bibliotecas principales de Dart se actualizaron recientemente con seguridad nula. Como ejemplo ilustrativo de compatibilidad con versiones anteriores, el reemplazo de las bibliotecas centrales existentes se realizó sin una sola prueba fallida y sin errores en las aplicaciones de prueba que se ejecutan en entornos de prueba Dart y Flutter. Incluso la actualización de las bibliotecas centrales para muchos de los clientes internos de Google se realizó sin problemas. Planeamos rediseñar todos nuestros paquetes y aplicaciones para usar la seguridad nula después del lanzamiento, esperamos que usted haga lo mismo. Pero puede hacerlo a su propio ritmo, lote por lote, aplicación por aplicación.

Estas palabras, sí para los desarrolladores de Swift, especialmente la tercera versión ...

Pero incluso aquí todo no es tan optimista, los propios desarrolladores dicen que al combinar código de seguridad nulo y código "antiguo" en un proyecto, no pueden garantizar la solidez sistemas de tipo.

Plan de acción adicional



Planeamos implementar la seguridad nula gradualmente en tres fases:



  1. Vista previa técnica. Se lanzó cuando se publicó el artículo original (10/06/2020) y está disponible en dev-branch. Vale la pena prestar atención a la sección "Empiece ahora". Todavía es muy inestable y está sujeto a cambios, por lo que no recomendamos usarlo todavía en el código de producción. ¡Pero nos encantaría saber de ti y darnos tu opinión!
  2. Versión beta. La seguridad nula estará disponible en la rama beta de Dart y ya no se esconderá detrás de una bandera experimental. La implementación será cercana a la versión final esperada. Será posible comenzar a migrar sus paquetes y complementos a pub.dev, pero no se recomienda publicar este cambio como una versión estable todavía.
  3. Versión estable. La seguridad nula estará disponible para todos. Se le pedirá que publique sus paquetes y complementos actualizados como versiones estables. También vale la pena migrar sus aplicaciones en esta etapa.


Si todo va según lo planeado, lanzaremos una versión estable de Dart con seguridad nula para fin de año. De vez en cuando, agregaremos herramientas para ayudarlo a moverse a la seguridad nula. Entre ellos:



  • Una herramienta de migración para ayudar a automatizar los muchos pasos de actualización de paquetes y aplicaciones existentes;
  • pub.dev, null safety;
  • 'pub outdated' , null safety.




La forma más rápida de probar la seguridad nula hoy en día es con nullsafety.dartpad.dev, la versión de DartPad con la seguridad nula habilitada. Abra la lista desplegable Learn with Snippets para encontrar una serie de tutoriales sobre la nueva sintaxis y los conceptos básicos de la seguridad nula.



imagen



También puede experimentar con seguridad nula en aplicaciones de consola pequeñas (todavía no hemos actualizado marcos más grandes como Flutter). Primero, debe descargar el SDK de Dart desde la rama de desarrollo, luego puede descargar esta aplicación de consola de ejemplo . El archivo README contiene instrucciones para ejecutar la aplicación con la función de seguridad nula experimental habilitada. Los otros archivos del ejemplo proporcionan configuraciones de ejecución que permitirán la depuración en VS Code y Android Studio.



También puede leer la documentación (aparecerán más en el futuro):





UPD: En los comentarios, sugerí este enlace Comprender la seguridad nula


Estamos muy emocionados de poder implementar la seguridad nula en Dart. El manejo confiable y seguro de enlaces vacíos se convertirá en el sello distintivo de Dart para ayudarlo a escribir el código más confiable y productivo. Esperamos que se tome un tiempo para experimentar con la versión actual de seguridad nula y deje sus comentarios en nuestro rastreador de errores. ¡Que tengas un buen código!

Gracias por leer hasta el final. La traducción se retrasó un poco, pero es de esperar que los comentarios hayan sido útiles para el material y no se haya convertido en una simple traducción. Me gustaría agregar que esta función es un paso adelante realmente útil para todo el ecosistema de Flutter. Espero poder usarlo ya en aplicaciones en vivo. Mientras tanto, como dicen en idioma extranjero, ¡estad atentos!



All Articles