Una introducción a la inmutabilidad con Dart

Es imposible negar que la inmutabilidad es un tema candente en programación, especialmente en programación front-end. Librerías como Immutable.js y…

Es imposible negar que la inmutabilidad es un tema candente en la programación, especialmente en la programación front-end. Librerías como Immutable.js y otros conceptos como el flujo de datos unidireccional han argumentado que es más fácil razonar sobre los datos cuando no cambian debajo de ti:

En la programación orientada a objetos y funcional, un objeto inmutable (objeto inmutable) es un objeto cuyo estado no puede modificarse después de ser creado. Esto contrasta con un objeto mutable (objeto modificable), que puede modificarse después de ser creado.

Bueno, ¿qué pasa con Dart? Tenemos un par de conceptos que se prestan bien a la inmutabilidad y a los objetos inmutables integrados, comenzando con el modificador const y el constructor const. No hay que confundirlo con const en ES6, que es simplemente un enlace inmutable:

javascript
// Define USER as a constant and give it an initial value.
const USER = { name: 'Joe'; }

// This will throw an error.
USER = {};

// But this will not.
USER.name = 'Jill';

En Dart, const es tanto un enlace inmutable como un objeto inmutable:

dart
main() {
  const user = const {'name': 'Joe'};

  // Static error: "Constant variables cannot be assigned a value".
  user = {};

  // Runtime error: "Unsupported operation: Cannot modify unmodifiable Map".
  user['name'] = 'Jill';
}

Todos los literales (Null, String, int, double, num, bool, Map, List, Symbol) pueden ser const, y es posible crear tipos de usuario con un constructor const:

dart
class User {
  final String name;

  const User(this.name);
}

main() {
  const user = const User('Joe');
}

Repasemos — las instancias const son tanto enlaces inmutables como forzadas a nivel del lenguaje para ser profundamente inmutables — y además son canonicalizadas en tiempo de compilación — es decir, dos instancias cualesquiera se consideran equivalentes, y solo están representadas por una única instancia en ejecución. Por ejemplo, lo siguiente es bastante económico — solo asigna una única instancia en tiempo de ejecución:

dart
class User {
  final String name;
  final List<String> cars;

  User(this.name, {this.cars});
}

main() {
  for (var i = 0; i < 100; i++) {
    const users = const {
      'Matan': const User(
        'Matan Lurey',
        cars: const [
          'Truck',
          'Jeep',
          'GoKart',
        ],
      ),
    };
  }
}

¿Quieres aprender más? Lee el tour del lenguaje Dart sobre final y const.

Verificación estática adicional con package:meta

#

Por supuesto, const es un poco restrictivo — debes poder crear una clase en tiempo de compilación — así que no podrías, por ejemplo, leer una base de datos y crear objetos const en tiempo de ejecución. Recientemente hemos introducido la anotación "immutable" con package:meta:

dart
import 'package:meta/meta.dart';

// Error: This class inherits from a class marked as @immutable, and therefore
// should be immutable (all instance fields must be final).
@immutable
class User {
  String name;
}

Puedes usar esta anotación para ayudar a asegurar que los desarrolladores mantengan tus clases profundamente inmutables. No será canonicalizada como const, pero aún puede ser bastante útil para los desarrolladores.

Espero que esta haya sido una buena introducción a la inmutabilidad. Por favor, déjame saber en los comentarios o en twitter si te gustaría aprender más sobre Dart o la inmutabilidad.

Más de Dart