dart-modern-features

Je remarque que vous avez fourni "|-" ce qui semble être un début incomplet de tableau Markdown. Pouvez-vous s'il vous plaît fournir le texte complet à traduire ? Je suis prêt à : 1. Traduire le contenu en français 2. Préserver strictement le formatage Markdown 3. Conserver les noms propres, marques et commandes techniques en anglais 4. Retourner uniquement la traduction Veuillez partager le texte que vous souhaitez faire traduire.

npx skills add https://github.com/flutter/skills --skill dart-modern-features

Fonctionnalités Modernes de Dart

1. Quand utiliser cette compétence

Utilisez cette compétence quand :

  • Vous écrivez ou vérifiez du code Dart ciblant Dart 3.0 ou une version ultérieure.
  • Vous refactorisez du code Dart legacy pour utiliser des fonctionnalités modernes, concises et sûres.
  • Vous recherchez des moyens idiomatiques de gérer plusieurs valeurs de retour, l'extraction de données imbriquées ou la vérification exhaustive.

Découverte

Pour trouver des candidats à la modernisation :

Switch Expressions

Recherchez les déclarations switch où chaque case assigne à la même variable ou retourne :

  • Regex : switch\s*\([^)]+\)\s*\{\s*case

Candidats Pattern Matching

Recherchez l'extraction manuelle de propriétés de map ou JSON et la vérification de type :

  • Regex : containsKey\(['"][^'"]+['"]\)
  • Regex : json\[['"][^'"]+['"]\]\s+is\s+

Éléments Null-Aware

Recherchez les déclarations if de collection vérifiant la nullité :

  • Regex : if\s*\(\w+\s*!=\s*null\)\s*\w+

Séparateurs de Chiffres

Recherchez les longs nombres sans séparateurs :

  • Regex : \b\d{6,}\b (Correspond aux nombres ayant 6 chiffres ou plus).

2. Fonctionnalités

Records

Utilisez les records comme des structures agrégées anonymes et immuables pour regrouper plusieurs objets sans définir de classe personnalisée. Préférez-les pour retourner plusieurs valeurs d'une fonction ou regrouper temporairement des données connexes.

À éviter : Créer une classe dédiée pour des retours simples à plusieurs valeurs.

class UserResult {
  final String name;
  final int age;
  UserResult(this.name, this.age);
}

UserResult fetchUser() {
  return UserResult('Alice', 42);
}

À préférer : Utiliser les records pour regrouper les types sans friction à la volée.

(String, int) fetchUser() {
  return ('Alice', 42);
}

void main() {
  var user = fetchUser();
  print(user.$1); // Alice
}

Patterns et Pattern Matching

Utilisez les patterns pour déstructurer les données complexes en variables locales et comparer contre des formes ou des valeurs spécifiques. Utilisez-les dans switch, if-case, ou les déclarations de variable pour déplier directement les données.

À éviter : Vérifier manuellement les types, les nulls et les clés pour l'extraction de données.

void processJson(Map<String, dynamic> json) {
  if (json.containsKey('name') && json['name'] is String &&
      json.containsKey('age') && json['age'] is int) {
    String name = json['name'];
    int age = json['age'];
    print('$name is $age years old.');
  }
}

À préférer : Combiner la vérification de type, la validation et l'assignation en une seule déclaration.

void processJson(Map<String, dynamic> json) {
  if (json case {'name': String name, 'age': int age}) {
    print('$name is $age years old.');
  }
}

Switch Expressions

Utilisez les switch expressions pour retourner une valeur directement, éliminant les déclarations case et break encombrantes.

À éviter : Utiliser les déclarations switch où chaque branche retourne ou assigne simplement une valeur.

String describeStatus(int code) {
  switch (code) {
    case 200:
      return 'Success';
    case 404:
      return 'Not Found';
    default:
      return 'Unknown';
  }
}

À préférer : Retourner l'expression évaluée directement en utilisant la syntaxe =>.

String describeStatus(int code) => switch (code) {
  200 => 'Success',
  404 => 'Not Found',
  _ => 'Unknown',
};

Class Modifiers

Utilisez les modificateurs de classe (sealed, final, base, interface) pour restreindre comment les classes peuvent être utilisées en dehors de leur bibliothèque définie. Préférez sealed pour définir des familles fermées de sous-types pour activer la vérification exhaustive.

À éviter : Utiliser des classes abstract ouvertes quand l'ensemble des sous-classes est connu et fixe.

abstract class Result {}

class Success extends Result {}
class Failure extends Result {}

String handle(Result r) {
  if (r is Success) return 'OK';
  if (r is Failure) return 'Error';
  return 'Unknown';
}

À préférer : Utiliser sealed pour garantir au compilateur que tous les cas sont couverts.

sealed class Result {}

class Success extends Result {}
class Failure extends Result {}

String handle(Result r) => switch(r) {
  Success() => 'OK',
  Failure() => 'Error',
};

Extension Types

Utilisez les extension types pour un wrapper à coût zéro autour d'un type existant. Utilisez-les pour restreindre les opérations ou ajouter un comportement personnalisé sans surcharge d'exécution.

À éviter : Allouer de nouveaux objets wrapper juste pour la logique spécifique au domaine ou la sécurité de type.

class Id {
  final int value;
  Id(this.value);
  bool get isValid => value > 0;
}

À préférer : Utiliser les extension types qui se compilent jusqu'au type sous-jacent à l'exécution.

extension type Id(int value) {
  bool get isValid => value > 0;
}

Digit Separators

Utilisez les underscores (_) dans les littéraux numériques strictement pour améliorer la lisibilité visuelle des grandes valeurs numériques.

À éviter : Les longs littéraux numériques qui sont difficiles à lire en un coup d'œil.

const int oneMillion = 1000000;

À préférer : Utiliser les underscores pour séparer les milliers ou d'autres groupements.

const int oneMillion = 1_000_000;

Wildcard Variables

Utilisez les wildcards (_) comme variables non-liantes ou paramètres pour signaler explicitement qu'une valeur est intentionnellement inutilisée.

À éviter : Inventer des noms de variable clunky et distincts pour éviter les avertissements "unused variable".

void handleEvent(String ignoredName, int status) {
  print('Status: $status');
}

À préférer : Explicitement abandonner la liaison avec un underscore.

void handleEvent(String _, int status) {
  print('Status: $status');
}

Null-Aware Elements

Utilisez les éléments null-aware (?) dans les littéraux de collection pour inclure conditionnellement des éléments seulement s'ils évaluent à une valeur non-null.

À éviter : Utiliser les déclarations if de collection pour les simples vérifications de null.

var names = [
  'Alice',
  if (optionalName != null) optionalName,
  'Charlie'
];

À préférer : Utiliser le préfixe ? en ligne.

var names = ['Alice', ?optionalName, 'Charlie'];

Dot Shorthands

Utilisez les dot shorthands pour omettre le nom de type explicite quand il peut être confiant déduit du contexte, comme avec les enums ou les champs statiques.

À éviter : Qualifier complètement les noms de type quand le type est évident dans le contexte.

LogLevel currentLevel = LogLevel.info;

À préférer : Réduire le bruit visuel avec le shorthand déduit.

LogLevel currentLevel = .info;

Compétences Connexes

  • dart-best-practices : Style de code général et idiomes Dart fondamentaux qui précèdent ou complètent les fonctionnalités de syntaxe modernes.