Decorators (ES7+) – Donner des super-pouvoirs aux fonctions et classes 🦸‍♂️✨

Decorators (ES7+) – Donner des super-pouvoirs aux fonctions et classes 🦸‍♂️✨

Parfois en JavaScript, vous voulez donner à une fonction ou une classe des pouvoirs supplémentaires, comme :

  • Logger chaque fois qu’elle est appelée
  • Valider automatiquement les paramètres
  • Mettre en cache des calculs lourds

Mais ajouter tout ce code à l’intérieur de chaque fonction… 😵‍💫 Chaos total du code !

C’est là que les decorators interviennent : ils vous permettent d’ajouter des super-pouvoirs aux fonctions ou classes sans toucher à leur code.


🧩 1. Qu’est-ce qu’un Decorator ?

Un decorator est une fonction magique qui prend une fonction ou une classe et l’améliore.

  • La fonction ou classe originale reste inchangée
  • Les decorators ajoutent un comportement supplémentaire
  • Ils sont réutilisables et maintiennent votre code propre

Analogie :

  • Fonction = un héros 🦸
  • Decorator = la cape magique du héros ✨
  • Résultat = un héros surpuissant 💥

🔹 2. Exemple simple : Logging Decorator

Scénario : Logger chaque fois qu’une fonction est appelée

JS classique :

function greet(name) {
  console.log(`Bonjour ${name} !`);
  console.log("La fonction greet a été appelée !");
}

greet("Alice");

⚠️ Problème : si vous avez 50 fonctions, vous devez ajouter ce code partout 😵
Répetitif et difficile à maintenir.


Avec Decorator :

function log(target, key, descriptor) {
  const original = descriptor.value; // Fonction originale
  descriptor.value = function(...args) {
    console.log(`${key} appelé avec les arguments : ${args}`);
    return original.apply(this, args); // Appelle la fonction originale
  };
  return descriptor;
}

class Greeter {
  @log
  greet(name) {
    console.log(`Bonjour ${name} !`);
  }
}

const g = new Greeter();
g.greet("Alice");

✅ Sortie :

greet appelé avec les arguments : Alice
Bonjour Alice !

📌 Explication :

  • @log → donne un super-pouvoir à la fonction ✨
  • target → la classe ou l’objet auquel appartient la fonction
  • key → nom de la méthode
  • descriptor.value → fonction originale
  • apply(this, args) → appelle la fonction originale avec ses arguments

💡 Astuce : Les decorators de logging sont très utiles pour le debug.


🧠 3. Validation Decorator

Parfois, les fonctions ont besoin de contrôles de sécurité : empêcher des paramètres manquants ou invalides.

function validate(target, key, descriptor) {
  const original = descriptor.value;
  descriptor.value = function(name) {
    if (!name) {
      throw new Error("Nom requis !");
    }
    return original.apply(this, [name]);
  };
  return descriptor;
}

class UserGreeter {
  @validate
  greet(name) {
    console.log(`Salut ${name} !`);
  }
}

const u = new UserGreeter();
u.greet(""); // ❌ Erreur : Nom requis !
u.greet("Alice"); // ✅ Salut Alice !

📌 Analogie amusante :
Ce decorator = un videur à la porte 🚪
Pas de nom ? “Tu ne passes pas !”

💡 Astuce :
Les decorators de validation sont parfaits pour les formulaires et entrées utilisateurs
Élimine le code répétitif


🧩 4. Caching Decorator

Certaines fonctions effectuent des calculs lourds.
Les decorators peuvent stocker les résultats, rendant les appels répétés ultra rapides ⚡

function cache(target, key, descriptor) {
  const original = descriptor.value;
  const memory = {};
  descriptor.value = function(num) {
    if(memory[num] !== undefined) {
      console.log(`Récupéré depuis le cache : ${num}`);
      return memory[num];
    }
    const result = original.apply(this, [num]);
    memory[num] = result;
    return result;
  };
  return descriptor;
}

class Calculator {
  @cache
  factorial(n) {
    console.log(`Calcul de : ${n} !`);
    return n <= 1 ? 1 : n * this.factorial(n - 1);
  }
}

const c = new Calculator();
console.log(c.factorial(5)); // Calcul en cours...
console.log(c.factorial(5)); // Récupéré depuis le cache !

📌 Explication :

  • memory → objet cache
  • Si le résultat a déjà été calculé, la valeur du cache est renvoyée
  • apply → exécute la fonction originale

💡 Astuce :

  • Parfait pour les fonctions gourmandes en CPU
  • Utilisez le caching decorator pour les appels API ou calculs lourds

🧠 5. Combiner les Decorators

Une fonction peut avoir logging, validation et caching appliqués ensemble.
L’ordre compte : validation → caching → logging est souvent logique.

class SuperGreeter {
  @log
  @cache
  @validate
  greet(name) {
    console.log(`Salut ${name} !`);
  }
}

Note : Les decorators sont appliqués de haut en bas, donc l’ordre influence le comportement.


🎉 6. Règles d’utilisation et conseils

  • Doivent être réutilisables
  • Ne doivent pas modifier la fonction ou classe originale
  • Maintiennent le code complexe propre et lisible
  • Permettent de combiner plusieurs decorators pour plus de super-pouvoirs

💡 Astuce bonus :
Logging + Validation + Caching = “Fonction surpuissante”
Approche moderne, propre et maintenable dans les nouveaux projets JS


🎯 7. Conclusion : Les Decorators font de vous un super-héros JS

  • Le code devient plus court, propre et lisible
  • Ajoutez facilement des fonctionnalités aux fonctions et classes
  • Automatisez les tâches répétitives comme le logging, la validation et le caching
  • Ressentez-vous comme un super-héros JavaScript 🦸‍♂️✨

Comments

No comments yet. Why don’t you start the discussion?

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir