Introduciendo Dart 3 alfa
Adelántate a la versión más productiva, portable y accesible de Dart hasta ahora. Ya disponible para pruebas tempranas y experimentación.
En diciembre, dimos un vistazo al futuro con nuestro primer blog post sobre Dart 3. Hoy — en vivo desde el Flutter Forward evento para desarrolladores en Nairobi, Kenia — estamos compartiendo la visión más amplia para el próximo gran release de Dart, y nuestra primera build de preview, Dart 3 alpha.
Nuestra misión para Dart es crear el mejor lenguaje de programación para construir apps de alta calidad en cualquier plataforma de apps. Dart es accesible, fácil de aprender, evita la complejidad innecesaria y es internamente consistente. Dart es productivo; los desarrolladores de apps están bajo constante presión para entregar apps con requisitos siempre cambiantes, en menos tiempo, pero con calidad y acabado sin concesiones. Así que, construimos Dart con un enfoque profundo en habilitar desarrollo rápido, iteración rápida y alta calidad. Y Dart es portable, abarcando el conjunto más amplio de plataformas, para permitirte desplegar apps a los dispositivos de hoy y de mañana.
Hemos trabajado en establecer estas cualidades durante muchos años. Con Dart 3, pretendemos dar otro gran paso, refinando y expandiendo la accesibilidad, productividad y portabilidad de formas significativas.
Dart 3 es un nuevo release major. En parte para significar el gran salto adelante en nuevas funcionalidades, y en parte porque es un release con breaking changes en términos de versionado semántico: Estamos cambiando el sistema de tipos para solo soportar sound null safety (en Dart 2.12 y posteriores esto era opt-in), y hemos hecho los breaking changes correspondientes en las bibliotecas core de Dart. ¡Veamos los detalles!
Mejoras de productividad en Dart 3
#Un lenguaje Dart más expresivo: Records, patterns y controles de acceso
#Hemos evolucionado el lenguaje Dart a un ritmo rápido en los últimos años, añadiendo 23 nuevas funcionalidades desde 2.0. En Dart 3 esperamos añadir dos nuevas funcionalidades principales, records y patterns, con el objetivo de hacer que trabajar con datos estructurados sea más productivo.
Los records permiten crear de forma eficiente y concisa valores compuestos anónimos a partir de cualquier dato existente, sin la sobrecarga conceptual de necesitar declarar una clase para contener los valores. Con los records, puedes construir fácilmente nuevas estructuras de datos que combinen datos existentes. Por ejemplo, para retornar un par de valores:
(double x, double y) geoLocation(String name) {
if (name == 'Nairobi') {
return (-1.2921, 36.8219);
} else {
...
}
}
Mientras que los records permiten combinar datos, los patterns pueden desestructurar datos compuestos en sus constituyentes. Por ejemplo, para desestructurar el valor de retorno de
geoLocation anterior (un record consistente en un par de ints) en dos variables int
individuales, lat y long, puedes usar una declaración con pattern como esta:
void main(List<String> arguments) {
final (lat, long) = geoLocation('Nairobi');
print('Current location: $lat, $long');
}
Los patterns son completamente type safe, y verificados durante el desarrollo.
También puedes hacer pattern matching sobre el tipo de los valores, por ejemplo de una jerarquía de clases. Un switch
puede usar patterns que coincidan con el tipo, y los campos individuales de cada tipo, como en el cuerpo de calculateArea
aquí:
sealed class Shape {
}
class Square implements Shape {
final double length;
Square(this.length);
}
class Circle implements Shape {
final double radius;
Circle(this.radius);
}
double calculateArea(Shape shape) => switch (shape) {
Square(length: var l) => l * l,
Circle(radius: var r) => math.pi * r * r
};
En general, estamos añadiendo una gran selección de patterns que, cuando se combinan, hacen Dart mucho más expresivo para datos estructurados.
En conjunto con los patterns, también estamos añadiendo controles de capacidades a las clases, mediante varios nuevos modificadores:
interface class: No puede ser extendida.-
base class: Deshabilita la interfaz implícita, así que no puede ser implementada. -
final class: No se puede extender, implementar ni mezclar la clase (fuera de la biblioteca actual). -
sealed class: Igual que abstract + final + el tipo se considera la raíz de una familia de tipos sealed para verificación de exhaustividad. Como ejemplo, toma laShapejerarquía de clases anterior. En sentencias switch sobre el tipoShape(como la funcióncalculateArea), el analyzer activará errores si la sentencia switch no maneja todos los subtipos posibles del tipo sealed. mixin class: Una clase que puede ser usada como mixin.
Cada nueva funcionalidad añade complejidad al lenguaje. Para asegurar que Dart siga siendo accesible, las clases por defecto son completamente permisivas igual que hoy, con la pequeña excepción de que las clases destinadas a usarse como mixins deben ahora usar la palabra clave
mixin.
Integración productiva de plataforma mediante interop directo con bibliotecas de plataforma
#Estamos trabajando en expandir la interoperabilidad del lenguaje Dart para llamar a bibliotecas de plataforma directamente desde Dart. En plataformas Apple, estamos construyendo sobre nuestro trabajo en FFI para interoperabilidad con C, que soporta llamar a cualquier módulo C que siga la convención de llamada de C desde Dart. Esto hasta ahora ha soportado lenguajes como C, Go y Rust. Ahora, estamos añadiendo soporte para Swift y Objective-C en iOS/macOS. En Android, puedes llamar a bibliotecas Jetpack escritas en Kotlin y bibliotecas de Android escritas en Java aprovechando FFI y la Java Native Interface (JNI) de Android.
Impulsado por nuevas herramientas, Dart puede crear automáticamente bindings que tienen una interfaz Dart y detrás de esos código de interop entre lenguajes basado en los archivos de header/interface del código original C/ObjC/Swift/Java/Kotlin. Para una demostración de usar esto para llamar al Core Motion API de Apple y al HealthConnect API de Android, revisa la app de ejemplo.
Estos nuevos mecanismos de interop son actualmente experimentales, pero esperamos que alcancen al menos calidad beta en Dart 3.0 estable. Se aprecian comentarios en los trackers de issues para Java/Kotlin, o C/ObjectiveC/Swift. Finalmente, también estamos trabajando en una interoperabilidad mejorada de Dart a JavaScript; tendremos más noticias sobre eso en un futuro blog post.
Avances en portabilidad
#Dart ya soporta una amplia gama de plataformas objetivo con nuestros compiladores nativos y web. En la web, actualmente compilamos a JavaScript. En dispositivos nativos, actualmente soportamos las arquitecturas Intel 32-bit y 64-bit, y ARM 32-bit y 64-bit. Hay una serie de dispositivos y estándares emergentes en los que estamos trabajando para añadir soporte, para asegurar que Dart esté listo para los dispositivos del futuro.
Para la web, estamos trabajando en soporte para WebAssembly (Wasm), que ha estado creciendo en madurez como un formato de instrucciones binarias neutral a la plataforma en todos los navegadores modernos. Es nuestra esperanza que Wasm pueda habilitar a las apps web de Dart a iniciar tan rápido como las apps en dispositivos nativos.
Otra arquitectura de plataforma creciendo en interés es RISC-V, una arquitectura de set de instrucciones (ISA) de estándar abierto diseñada para uso amplio. El equipo de Android recientemente dio una charla sobre su trabajo para soportar RISC-V, y creemos que tendrá amplia aplicabilidad para dispositivos embebidos también. El soporte para RISC-V está disponible para preview en Dart 3 alpha.
Finalmente, estamos trabajando en expandir nuestro soporte actual para dispositivos ARM para abarcar también el soporte de ARM64 en Windows.
Breaking changes en Dart 3
#Con las nuevas capacidades de Dart 3 cubiertas, pasemos a los breaking changes que estamos haciendo en el espíritu de un Dart más consistente y accesible.
Sistema de tipos de Dart 3: 100% sound null safety
#Introdujimos sound null safety en Dart 2.12 en 2021. En un sistema de tipado sound, puedes confiar en los tipos, lo que significa que una variable es nunca null cuando los tipos indican que no lo es. Esto aumenta la productividad al detectar problemas durante el desarrollo en lugar de en producción, y habilita a los compiladores de Dart para producir código más pequeño y más optimizado. Como discutimos en diciembre, Dart es único al introducir 100% sound null safety a un lenguaje existente.
Desde Dart 2.12, null safety ha sido una opción de configuración que podía estar activada o desactivada. En Dart 3, todo el código se ejecuta con sound null safety activado. Ya no es posible ejecutar apps sin null safety o en un modo mixto con null safety parcial.
Somos conscientes de que discontinuar el soporte para ejecutar sin null safety puede plantear problemas para apps y paquetes existentes. Sin embargo, creemos que ahora es el momento adecuado para avanzar con este cambio. Tener un único sistema de tipos, donde null safety siempre está activo, reduce la sobrecarga y la complejidad. Siempre que los desarrolladores lean un fragmento de código de Dart 3, pueden tener la seguridad de que todas las variables son non-null por defecto. En el lado de la implementación, los compiladores y runtimes de Dart pueden enfocarse en soportar una única forma de ejecutar código Dart, lo que reduce el costo y la complejidad de añadir nuevas funcionalidades.
El ecosistema de Dart ha demostrado una fuerte dedicación y disposición para migrar código existente a null safety. A día de hoy,
100% de los top-250 paquetes en pub.dev soportan null safety
98% de los top-1000 paquetes en pub.dev soportan null safety
Solo el 14% de las sesiones de flutter run aún se ejecutan sin null safety
¡Gracias al ecosistema por el esfuerzo de migración!
Limpieza de las bibliotecas core y del lenguaje en Dart 3
#A medida que el lenguaje Dart y el sistema de tipos han evolucionado, varias de las APIs en nuestras bibliotecas core se han vuelto redundantes o subóptimas. Para asegurar que Dart siga siendo accesible, hemos hecho una serie de breaking changes para limpiar APIs innecesarias. Para más detalles, consulta los issues de GitHub, #34233 y #49529. También hemos eliminado una sintaxis histórica para valores por defecto de parámetros (#2357).
Con Dart 3 alpha listo, nuestra atención se ha vuelto ahora a Dart 3 beta. Allí, esperamos refinar aún más las bibliotecas core de Dart añadiendo una serie de nuevas APIs. Puedes dar tu opinión en el issue de feedback.
Preparando tu código para Dart 3 estable
#En general, creemos que la mayoría del código que ya se ha migrado para usar null safety, usando Dart 2.12 o posterior, funcionará con Dart 3. Sin embargo, un pequeño subconjunto de paquetes y apps puede verse afectado por los breaking changes discutidos arriba. Así que, para darte tiempo para prepararte para el release estable de Dart 3 más adelante este año, no hemos planeado más breaking changes al lenguaje y bibliotecas core de Dart después de Dart 3 alpha.
Para aprovechar el código que ya se ha migrado para usar null safety, hemos implementado compatibilidad hacia atrás en Dart 3 que permitirá a los paquetes migrados resolverse con
pub get en Dart 3 a pesar de tener una restricción de versión de SDK como >=2.12 <3.0.0, siempre y cuando no dependan de otras APIs de bibliotecas core o funcionalidades del lenguaje discontinuadas. Para más detalles, incluyendo cómo probar con un
Dart 3 alpha SDK instalado localmente, consulta nuestra documentación de null safety de Dart 3.
Para los paquetes publicados en el repositorio pub.dev, hemos ejecutado análisis con Dart 3 alpha, y etiquetado los paquetes que pasan con una etiqueta de "Dart 3 ready". Esto significa que el paquete probablemente funcionará con Dart 3 cuando se lance estable más adelante este año.
Limpieza de herramientas en Dart 3
#Liderando hacia Dart 3, hicimos una serie de cambios para mover todas nuestras herramientas de terminal para desarrolladores a una herramienta unificada dart, lo que hizo Dart mucho más accesible para nuevos desarrolladores. Estamos planeando cambios adicionales en las herramientas en los próximos meses para limpiar aún más. Esperemos que estos cambios no sean demasiado disruptivos, pero se debe esperar algo de ruptura menor para las herramientas en Dart 3 beta.
Próximos pasos
#Dart 3 alpha está disponible hoy en el canal dev de Dart y en el canal master de Flutter. Te invitamos a probarlo, ya sea para experimentar con las nuevas funcionalidades del lenguaje como records y patterns, probar nuestro nuevo interop de acceso directo a plataforma, o probar tus apps y paquetes para compatibilidad con Dart 3.
Continuaremos refinando Dart 3 en los próximos meses, y esperamos tener un release completo de Dart 3 estable más adelante este año. Ten en cuenta que la mayoría de las funcionalidades aún están en desarrollo, y por lo tanto sujetas a cambios hasta el release estable. Hasta entonces, ¡diviértete con tu código Dart!
Más de Dart
El eslabón perdido de Flutter: Por qué Dart full-stack lo cambia todo
Con el soporte de Cloud Functions for Firebase para Dart, podemos tratar toda la pila como una sola aplicación unificada.
Anunciando Genkit Dart: Construye aplicaciones AI full-stack con Dart y Flutter
Anunciando el lanzamiento en preview de Genkit Dart, un framework de AI de código abierto para construir aplicaciones full-stack con AI para cualquier plataforma.