Architecture orientée événements en TypeScript : quand le code « s'entend » mutuellement
\n\nImaginez que vous développez une application web complexe : un messager, un bot de trading ou un système de surveillance de serveurs. À un moment donné, vous réalisez : appeler simplement des fonctions en chaîne, c'est l'enfer. Un module en entraîne un autre, le troisième dépend du quatrième, et lorsque la logique change, tout s'effondre comme un château de cartes.
\n\nCela vous semble familier ? Alors vous avez besoin de l'architecture orientée événements en TypeScript. Ce n'est pas juste un terme à la mode, mais une véritable façon de rendre le code flexible, extensible et compréhensible. Dans cet article, nous allons voir comment fonctionne la programmation orientée événements, créer notre propre bus d'événements en TypeScript et observer où cela est vraiment utile.
\n\nQu'est-ce que l'architecture orientée événements en termes simples
\n\nL'architecture orientée événements est une approche où les composants du système communiquent via des événements. Un module génère un événement (par exemple, « utilisateur inscrit »), et d'autres s'y abonnent et réagissent. Ils ne sont pas directement liés entre eux.
\n\nCela semble abstrait ? Prenons un exemple de la vie réelle. Imaginez un bureau :
\n- \n
- Approche traditionnelle : le chef s'approche personnellement de chaque employé et dit : « Fais le rapport ». \n
- Approche orientée événements : le chef crie : « Il faut un rapport ! » — et tous ceux qui savent le faire se mettent au travail. \n
Dans le second cas, le chef n'a pas besoin de savoir qui fera exactement le rapport. Il envoie simplement l'événement. Et les employés peuvent se connecter et se déconnecter sans modifier la logique du chef. C'est l'essence même de la programmation orientée événements.
\n\nPourquoi TypeScript est idéal pour l'architecture événementielle
\n\nJavaScript est lui-même orienté événements (souvenez-vous de addEventListener), mais dans les grands projets, sans typage, c'est le chaos. Les événements TypeScript résolvent ce problème : vous savez exactement quelles données arrivent dans l'événement, et le compilateur détectera l'erreur au moment du développement, et non à l'exécution.
De plus, TypeScript prend en charge les génériques, les surcharges et le typage strict des callbacks — tout ce qu'il faut pour créer un bus d'événements fiable.
\n\nCréer un Event Bus en TypeScript à partir de zéro
\n\nCommençons par un exemple simple mais fonctionnel. Créons une classe EventBus — un bus d'événements central par lequel tous les modules communiqueront.
// event-bus.ts\ntype EventHandler<T = any> = (data: T) => void;\n\nclass EventBus {\n private handlers: Map<string, EventHandler[]> = new Map();\n\n // Abonnement à un événement\n on<T>(event: string, handler: EventHandler<T>): void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, []);\n }\n this.handlers.get(event)!.push(handler as EventHandler);\n }\n\n // Désabonnement d'un événement\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n this.handlers.set(event, handlers.filter(h => h !== handler));\n }\n }\n\n // Émission d'un événement\n emit<T>(event: string, data: T): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n handlers.forEach(handler => handler(data));\n }\n }\n}\n\nexport const globalEventBus = new EventBus();\n\nVoilà, nous avons écrit une simple architecture orientée événements en TypeScript. Désormais, n'importe quel module peut importer globalEventBus et soit écouter les événements, soit les générer.
Exemple d'utilisation : notifications et journalisation
\n\nImaginons que nous ayons un module d'authentification et un module de notifications. Ils ne doivent pas se connaître directement.
\n\n// auth-module.ts\nimport { globalEventBus } from './event-bus';\n\nexport function loginUser(email: string): void {\n // ... logique de connexion\n console.log(`Utilisat