Cómo el null safety de Dart me ayudó a mejorar mis proyectos
Migré una aplicación en ejecución y un paquete publicado a null safety, ¡y fue increíble!
Sobre el autor: Waleed Arshad es un tecnólogo móvil fundamental, un desarrollador multiplataforma apasionado y la primera persona de Pakistán en convertirse en Google Developer Expert para Flutter. Después de graduarse de FAST Karachi, ha estado trabajando en la industria por más de cinco años y actualmente trabaja en el equipo de Developer Experience para Flutter en Tendermint. También lidera la comunidad de Flutter de Pakistán.
Con el lanzamiento de Flutter 2, null safety estuvo disponible en el canal estable de Flutter. Este post habla sobre mis experiencias personales migrando mis apps y paquetes a null safety, además de crear apps null-safe desde cero. En resumen, ¡los resultados fueron increíbles!
Si no conoces la función de null safety de Flutter, consulta el anuncio de null safety. Si quieres entender completamente null safety, consulta la documentación de Dart sobre null safety.
Este artículo describe dos de mis experiencias con null safety:
Migrando una app y un paquete
Escribiendo código nuevo en un entorno null-safe
Migrando una app y un paquete
#Cuando actualicé Flutter por primera vez a la versión 2.0 (la que soporta null safety) y actualicé la versión de mi Dart SDK a 2.12 en el archivo
pubspec.yaml de mi app de Flutter, vi muchos errores. Inicialmente quería probar una migración manual a null safety (es decir, migrar sin la herramienta de migración), así que comencé a resolver los errores de null safety manualmente — añadiendo signos de interrogación y exclamación por todo mi código. Hice todo ese trabajo intencionalmente, ¡solo para entender todo el arduo trabajo realizado por el equipo de Flutter en la
herramienta de migración de null safety para automatizar el proceso de cambio y actualización del código! Después de algo de experimentación, revertí todos los cambios manuales que había hecho a mano, y usé la magia de la herramienta para completar la migración de mi app.
La aplicación era una app experimental de estadísticas de COVID-19, y su código es completamente de código abierto. Puedes encontrarlo en GitHub.
Fue realmente genial ver todos los cambios de código que hizo la herramienta de migración en mi proyecto — cambios como añadir signos de interrogación en nullables y añadir signos de exclamación donde la herramienta de migración detectó que el valor nunca iba a ser null.
El siguiente es un ejemplo de la herramienta de migración añadiendo automáticamente signos de interrogación y exclamación.
_homeCountry es una propiedad nullable de una clase llamada HomeCountry (que también es nullable). Por lo tanto, para proteger el acceso a una de las propiedades de
_homeCountry, la herramienta añadió el operador de signo de interrogación.
Después de la migración, algunos problemas en el código se hicieron evidentes, lo cual es la mejor parte.
Uno de los problemas era que algunas strings nullable se estaban pasando como una lista a una función interna del plugin
shared_preferences. Como estos valores eran nullable, la herramienta hizo que el tipo de toda la lista fuera
<String?>[], lo cual empezó a dar un error porque la función aceptaba el tipo
<String>[].
Una solución simple a este problema era eliminar el signo de interrogación y hacer que el tipo de la lista coincidiera con el tipo del parámetro de la función. Cuando hice eso, el analyzer empezó a decir que un tipo nullable (String?) no puede asignarse a un tipo non-nullable (String).
Para resolver el problema, hice que cada propiedad de la clase HomeCountry fuera non-nullable y añadí la palabra clave
required en el constructor. Eso significaba que ahora era necesario pasar los argumentos al inicializar
HomeCountry. No tuve que cambiar la función setHomeCountry porque las variables que se pasaban a la lista ahora eran non-nullable.
Este cambio me impidió enviar por error un valor null a shared preferences en mi código, ¡lo cual fue una contribución muy valiosa de la función de null safety!
Otra cosa que encontró null safety fue un bug que podía causar un crashe en tiempo de ejecución. Mira el siguiente fragmento de código:
Como list era una variable nullable, leer sus elementos basados en índice podía causar un crashe. Después de migrar a null safety, no pude compilar la app porque no había una verificación de null antes de leer los valores en esta lista.
Finalmente, añadí una verificación de null para hacer que el código compilara y para evitar que la app crasheara en este punto del código. ¡Es increíble cómo la migración me ayudó a encontrar un bug real!
También me pasó migrar un paquete muy pequeño, que puedes encontrar en pub.dev, llamado
progress_indicators. Me sorprendió ver cómo la herramienta de migración añadió palabras clave
late en lugar de signos de interrogación cuando concluyó que esas variables se inicializaban antes de ser usadas.
Escribiendo código nuevo en un entorno null-safe
#Ahora que Flutter tiene null safety, crear apps nuevas es una mejor experiencia de desarrollo. Escribir código nuevo en un entorno null-safe también proporciona una mejor comprensión de los flujos de código, además de poder escribir código a prueba de crasheos. Ya no puedes crear código compilable con una clase como esta ahora:
class MyClass {
String a;
MyClass({this.a});
}
Este código causa un error en tiempo de compilación que dice que marques a como nullable, pongas una palabra clave required
en el constructor, o añadas un inicializador. El código se asegura de que a nunca sea null. Entonces, dependiendo de tu caso de uso, podrías hacer esto:
class MyClass {
String? a;
MyClass({this.a});
}
O podrías hacer esto:
class MyClass {
String a;
MyClass({required this.a});
}
Ten en cuenta que no pones un signo de arroba (
@) antes de la palabra claverequired, a partir de Flutter 2 (y Dart 2.12).
O podrías mantener a como opcional, pero añadir un inicializador dándole un valor por defecto si no se pasa uno:
class MyClass {
String a;
MyClass({this.a = ''});
}
Además, ahora puedes crear variables nullable de tus propias clases creadas:
class MyClass {
String? a;
MyClass({this.a});
}
// somewhere in main code
MyClass? myClass;
Como myClass tiene un tipo nullable, tu compilador dará un error si escribes algo como esto:
print(myClass.a);
Aquí está el error:
La propiedad 'a' no puede ser accedida incondicionalmente porque el receptor puede ser 'null'.
Puedes arreglar ese error añadiendo un signo de interrogación:
print(hello?.a);
La función de null safety de Dart se asegura de que escribas código menos vulnerable y más seguro. Detectar errores relacionados con variables null durante el tiempo de compilación es una adición valiosa a la experiencia de desarrollo. El ejemplo anterior muestra cómo el compilador te impide compilar el código siempre que detecta la posibilidad de que una excepción de puntero null cause que la app crashee en tiempo de ejecución. Esto significa claramente que el compilador intenta escribir código null-safe tanto como sea posible (a menos que uses el operador
! para forzar el desempaquetado de todo).
En conclusión, el sound null safety de Dart es un gran punto de partida para construir apps más seguras, rápidas y confiables. La experiencia general de programación ahora está muy estructurada y más organizada. Recomiendo que migres tus apps antiguas de Dart a null safety para entender cómo funciona. ¡Quizás tengas la suerte de encontrar y arreglar algunos bugs en tu código antiguo!
¡Feliz programación! :)
Más de Dart
Dart en Google Summer of Code 2026
¡Estamos emocionados de anunciar que el proyecto Dart será mentor de contribuidores por séptima vez en Google Summer of Code 2026!
Resultados de Google Summer of Code 2025
El programa Google Summer of Code (GSoC) se enfoca en involucrar a nuevos desarrolladores de todo el mundo con el desarrollo de software de código abierto. Google…