Contenidos

Descripción general de Dart

Dart product logo

Dart es un lenguaje optimizado para el cliente para desarrollar aplicaciones rápidas en cualquier plataforma. Su objetivo es ofrecer el lenguaje de programación más productivo para el desarrollo multiplataforma, junto con una plataforma de ejecución flexible para frameworks de aplicaciones.

Los lenguajes se definen por su envoltura técnica: las elecciones realizadas durante el desarrollo que dan forma a las capacidades y fortalezas de un lenguaje. Dart está diseñado para una envoltura técnica que es particularmente adecuado para el desarrollo del cliente, priorizando tanto el desarrollo (recarga en caliente con estado en menos de un segundo) como las experiencias de producción de alta calidad en una amplia variedad de objetivos de compilación (web, dispositivos móviles y de escritorio).

Dart también constituye la base de Flutter. Dart proporciona el lenguaje y los runtimes que impulsan las aplicaciones de Flutter, pero Dart también admite muchas tareas principales del desarrollador, como formatear, analizar y testing de código.

Dart: El lenguaje

El lenguaje Dart es de tipado seguro; utiliza verificación de tipado estático para garantizar que el valor de una variable siempre coincida con el tipo estático de la variable. A veces, esto se conoce como sound typing. Aunque los tipos son obligatorios, las anotaciones de tipo son opcionales debido a la inferencia de tipos. El sistema de tipado de Dart también es flexible y permite el uso de un tipo dynamic combinado con comprobaciones en tiempo de ejecución, que pueden ser útiles durante la experimentación o para código que necesita ser especialmente dinámico.

Dart tiene null safety ⬀ incorporado. Esto significa que los valores no pueden ser nulos a menos que tú digas que pueden serlo. Con un sólido null safety, Dart puede protegerte de excepciones null en tiempo de ejecución mediante análisis de código estático. A diferencia de muchos otros lenguajes null-safe, cuando Dart determina que una variable no admite valores null, esa variable nunca puede ser nula. Si inspeccionas tu código en ejecución en el depurador, verás que la no capacidad de nulidad se conserva en tiempo de ejecución; por lo tanto permanece null safety.

El siguiente ejemplo de código muestra varias características del lenguaje Dart, incluidas bibliotecas, llamadas asíncronas, tipos que aceptan valores null y no null, sintaxis de flechas, generadores, streams y getters. Para obtener más información sobre el lenguaje, realiza el tour del lenguaje Dart ⬀.

import 'dart:math' show Random;

void main() async {
  print('Compute π using the Monte Carlo method.');
  await for (final estimate in computePi().take(100)) {
    print('π ≅ $estimate');
  }
}

/// Generates a stream of increasingly accurate estimates of π.
Stream<double> computePi({int batch = 100000}) async* {
  var total = 0; // Inferred to be of type int
  var count = 0;
  while (true) {
    final points = generateRandom().take(batch);
    final inside = points.where((p) => p.isInsideUnitCircle);

    total += batch;
    count += inside.length;
    final ratio = count / total;

    // Area of a circle is A = π⋅r², therefore π = A/r².
    // So, when given random points with x ∈ <0,1>,
    // y ∈ <0,1>, the ratio of those inside a unit circle
    // should approach π / 4. Therefore, the value of π
    // should be:
    yield ratio * 4;
  }
}

Iterable<Point> generateRandom([int? seed]) sync* {
  final random = Random(seed);
  while (true) {
    yield Point(random.nextDouble(), random.nextDouble());
  }
}

class Point {
  final double x;
  final double y;

  const Point(this.x, this.y);

  bool get isInsideUnitCircle => x * x + y * y <= 1;
}

Dart: Las bibliotecas

Dart tiene un amplio conjunto de bibliotecas del core ⬀, que proporcionan elementos esenciales para muchas tareas de programación cotidianas:

  • Tipos integrados, colecciones y otras funciones del core para cada programa Dart (dart:core)
  • Tipos enriquecidos de colecciones, como colas, listas enlazadas, mapas hash y árboles binarios (dart:collection)
  • Codificadores y decodificadores para convertir entre diferentes representaciones de datos, incluidos JSON y UTF-8 (dart:convert)
  • Constantes y funciones matemáticas, y generación de números aleatorios (dart:math)
  • Soporte para archivos, sockets, HTTP y otras E/S para aplicaciones no web (dart:io)
  • Soporte para programación asincrónica, con clases como Future y Stream (dart:async)
  • Listas que manejan eficientemente datos de tamaño fijo (por ejemplo, enteros de 8 bytes sin signo) y tipos numéricos SIMD (dart:typed_data)
  • Interfaces de funciones externas para interoperabilidad con otro código que presenta una interfaz estilo C (dart:ffi)
  • Programación concurrente usando aislamientos: workers independientes que son similares a los hilos pero no comparten memoria y se comunican solo a través de mensajes (dart:isolate)
  • Elementos HTML y otros recursos para aplicaciones basadas en web que necesitan interactuar con el navegador y el Modelo de objetos de Documento (DOM) (dart:html)

Más allá de las bibliotecas del core, muchas API se proporcionan a través de un conjunto completo de paquetes. El equipo de Dart publica muchos paquetes complementarios útiles, como estos:

Además, los autores externos y la comunidad en general publican miles de paquetes, con soporte para características como estas:

Para ver una serie de ejemplos prácticos que presentan las bibliotecas principales de Dart, realiza el tour por la biblioteca ⬀. Para encontrar API adicionales, consulta la página de paquetes utilizados habitualmente ⬀.

Dart: Las plataformas

La tecnología de compilación de Dart te permite ejecutar código de diferentes maneras:

  • Plataforma nativa: para aplicaciones dirigidas a dispositivos móviles y de escritorio, Dart incluye tanto una máquina virtual Dart con compilación just-in-time (JIT) como una versión de compilador ahead-of-time (AOT) para producir código de máquina.

  • Plataforma web: para aplicaciones orientadas a la web, Dart puede compilar con fines de desarrollo o producción. Su compilador web traduce Dart a JavaScript.

An illustration of the targets supported by Dart

El framework Flutter es un popular conjunto de herramientas de interfaz de usuario multiplataforma que funciona con la plataforma Dart y que proporciona herramientas y bibliotecas de UI para crear experiencias de UI que se ejecutan en iOS, Android, macOS, Windows, Linux y la web.

Dart Nativo (código máquina JIT y AOT)

Durante el desarrollo, un ciclo de desarrollo rápido es fundamental para la iteración. Dart VM ofrece un compilador just-in-time (JIT) con recompilación incremental (que permite la recarga en caliente), colecciones de métricas en vivo (impulsando DevTools ⬀) y soporte completo de depuración.

Cuando las aplicaciones están listas para implementarse en producción, ya sea que las estés publicando en una tienda de aplicaciones o implementándolas en un backend de producción, el compilador ahead-of-time de Dart (AOT) puede compilar en ARM nativo o código de máquina x64. Tu aplicación compilada con AOT se inicia con un tiempo de inicio breve y constante.

El código compilado por AOT se ejecuta dentro de un runtime eficiente de Dart que aplica el sistema de tipado de Dart y administra la memoria mediante una rápida asignación de objetos y un recolector de basura generacional.

Más información:

Dart Web (JavaScript dev & prod)

Dart Web permite ejecutar código Dart en plataformas web con tecnología JavaScript. Con Dart Web, compilas código Dart en código JavaScript, que a su vez se ejecuta en un navegador—por ejemplo, V8 dentro de Chrome.

Dart web contiene dos modos de compilación:

  • Un compilador de desarrollo incremental que permite un ciclo de desarrollo rápido
  • Un compilador de producción optimizado que compila código Dart en JavaScript rápido, compacto y desplegable. Estas eficiencias provienen de técnicas como la eliminación de códigos muertos.

Más información:

El runtime de Dart

Independientemente de la plataforma que utilices o de cómo compiles tu código, la ejecución del código requiere un runtime de Dart. Este runtime es responsable de las siguientes tareas críticas:

  • Administrar la memoria: Dart usa un modelo de memoria administrada, donde un recolector de basura (GC) recupera la memoria no utilizada.

  • Aplicar el sistema de tipado de Dart: aunque la mayoría de las comprobaciones de tipos en Dart son estáticas (tiempo de compilación), algunas comprobaciones de tipos son dinámicas (tiempo de ejecución). Por ejemplo, el runtime de Dart aplica comprobaciones dinámicas por operadores de cast y comprobaciones de tipos ⬀.

  • Administración de aislamientos ⬀: el runtime de Dart controla el aislamiento principal (donde normalmente se ejecuta el código) y cualquier otro aislamiento que la aplicación crea.

En plataformas nativas, el runtime de Dart se incluye automáticamente dentro de ejecutables autónomos y es parte de la VM de Dart proporcionado por el comando dart run.

Aprendiendo Dart

Tienes muchas opciones para aprender Dart. Aquí hay algunas que recomendamos: