Question Pourquoi les gens utilisent-ils des bus de messages / d'événements dans leur code?


Je pense que vous avez entendu parler des bus de messages / d'événements, c'est le seul endroit où tous les événements du système circulent. Des architectures similaires se trouvent dans les cartes mères et les réseaux LAN. C'est une bonne approche pour les cartes mères et les réseaux car cela réduit le nombre de fils, mais est-ce bon pour le développement de logiciels? Nous n'avons pas de restrictions telles que l'électronique.

L'implémentation la plus simple du bus de messages / du bus d'événements peut être la suivante:

class EventBus {
    void addListener(EventBusListener l}{...}
    void fireEvent(Event e) {...}
}

La publication d'événements est effectuée avec bus.fireEvent (event), la réception des messages est activée par bus.addListener (listener). De telles architectures sont parfois utilisées pour le développement de logiciels, par exemple MVP4G implémente un bus de messages similaire pour GWT.

Projets actifs:

Projets inactifs / morts:

Ce n'est que le populaire modèle Observer (Listener) créé «globalement» - chaque objet du système peut écouter chaque message, et je pense que c'est mauvais, il rompt le principe d’encapsulation (chaque objet connaît tout) et le principe de responsabilité unique certains objets ont besoin d'un nouveau type de message, le bus d'événements doit souvent être modifié, par exemple, pour ajouter une nouvelle classe Listener ou une nouvelle méthode dans la classe Listener).

Pour ces raisons, je pense que pour la plupart des logiciels, le modèle Observer est meilleur que le bus d'événements. Que pensez-vous du bus d’événement, est-ce que cela a du sens pour les applications typiques?

EDIT: Je ne parle pas de «grandes» solutions d'entreprise telles que ESB - elles peuvent être utiles (ce qui est plus que ESB offre bien plus qu'un simple bus événementiel). Je m'interroge sur l'utilité d'utiliser le bus de messages dans le code Java "normal" pour la connexion objet-objet - certaines personnes le font, consultez les liens ci-dessus. Le bus d'événement est probablement la meilleure solution pour la communication téléphonique à téléphone ou la communication entre ordinateurs, car chaque téléphone (ou ordinateur) d'un réseau peut généralement se parler et le bus réduit le nombre de fils. Mais les objets se parlent rarement - combien de collaborateurs un objet peut avoir - 3, 5?


58
2017-10-21 12:25


origine


Réponses:


Certaines personnes l'aiment parce que c'est l'incarnation du Motif de façade ou Motif de médiateur. Il centralise les activités transversales telles que la journalisation, l'alerte, la surveillance, la sécurité, etc.

Certaines personnes ne l'aiment pas parce que c'est souvent un échec Singleton. Tout le monde doit le savoir.


23
2017-10-21 12:33



J'envisage d'utiliser un bus d'événement en mémoire pour mon code java habituel et ma justification est la suivante

Chaque objet du système peut écouter chaque message et je pense que   mauvais, il casse le principe d'encapsulation (chaque objet sait à propos de   tout)

Je ne suis pas sûr que cela soit vraiment vrai, je dois commencer par la classe avec le bus d'événements, semblable au modèle d'observateur. Une fois qu'une classe est enregistrée avec le bus d'événements, seules les méthodes qui ont la signature et l'annotation appropriées sont notifiées. .

et principe de responsabilité unique (par exemple, lorsque certains objets doivent   nouveau type de message, le bus d'événements doit souvent être modifié, par exemple   ajouter une nouvelle classe Listener ou une nouvelle méthode dans la classe Listener).

Je suis totalement en désaccord avec

bus d'événements doit souvent être changé

Le bus d'événement n'est jamais modifié

je suis d'accord avec

add a new Listener class or a new method in the Listener class

Comment cela brise-t-il SRP?, Je peux avoir un BookEventListener qui s'abonne à tous les événements relatifs à mon entité de livre, et oui je peux ajouter des méthodes à cette classe mais cette classe est toujours cohérente ...

Pourquoi je prévois de l'utiliser? Cela m'aide à modéliser le "quand" de mon domaine ....

Habituellement, nous entendons quelque chose comme envoyer un mail "quand" le livre est acheté

nous allons écrire

book.purchase();
sendEmail()

On nous dit ensuite d'ajouter un journal d'audit lorsqu'un livre est acheté, nous allons à l'extrait ci-dessus

book.purchase();
sendEmail();
**auditBook();**

Juste là OCP violé

Je préfère

book.purchase();
EventBus.raiseEvent(bookPurchasedEvent);

Continuez ensuite à ajouter des gestionnaires si nécessaire. Ouvrez pour l'extension fermée pour modification

Merci


63
2018-01-24 09:28



Je l'utilise beaucoup en JavaScript. Il peut y avoir tellement de widgets différents qui doivent tous faire quelque chose chaque fois que quelque chose d'autre se produit - il n'y a pas de véritable hiérarchie de propriété des objets. Au lieu de passer des références de chaque objet à chaque objet, ou simplement de rendre chaque objet global, quand quelque chose d'important se produit dans un widget particulier, je peux simplement publier "/ thisWidget / somethingHappened" - au lieu de remplir ce widget à l'API des autres widgets. Le je ai une seule classe qui contient tous les "câblage", ou "plubming" comme ils aiment l'appeler dans le cadre Java Spring. Cette classe contient des références à tous mes widgets et contient tout le code correspondant à ce qui se passe après chaque événement.

Il est centralisé, facile d’accès et de maintenance, et si une chose change ou si je souhaite un nouveau processus sur un événement spécifique, je n’ai pas à chercher dans chaque classe / objet / widget pour essayer de trouver est en cours de traitement. Je peux simplement aller à ma classe "opérateur" - celle qui gère tout le "câblage" lorsqu'un événement particulier se produit, et voir chaque répercussion de cet événement. Dans ce système, chaque widget individuel est complètement indépendant de l’API des autres widgets. Il publie simplement ce qui lui est arrivé ou ce qu’il fait.


15
2017-10-21 15:01



J'ai du mal à comprendre ce que tu es vraiment demander dans votre question. Vous donnez un exemple d'un bus d'événement simple qui est en fait juste Observable avec un nom différent, alors vous dites;

Pour ces raisons, je pense que pour   la plupart des logiciels, le modèle Observer est   mieux que le bus événementiel. Que faites-vous   penser à l'événement bus, fait-il   tout bon sens pour typique   applications?

..mais compte tenu de votre exemple, ils sont les mêmes. Cela me fait me demander si vous avez déjà utilisé quelque chose comme un bus de service d'entreprise. Au niveau de base, un ESB fait logiquement la même chose que le modèle de l'observateur, mais les produits commerciaux ajoutent beaucoup, beaucoup plus. C'est comme un bus d'événement sur les stéroïdes. Ce sont des produits logiciels complexes et des offres;

Récupération de message
Générez des événements en écoutant divers points de terminaison. Le noeud final peut être un écouteur (tel qu'un serveur HTTP), un système de messagerie (tel que JMS), une base de données ou à peu près tout ce que vous voulez.

Routage des messages
Prenez votre événement et envoyez-le à un / plusieurs endpoint. Le routage peut être assez intelligent, le bus peut acheminer le message en fonction du type de message, du contenu du message ou de tout autre critère. Le routage peut être intelligent et dynamique.

Transformation de message
Transforme votre message dans un autre format, il peut être aussi simple que XML ou JSON ou entre une ligne d'une table de base de données et une requête HTTP. La transformation peut se produire dans les données elles-mêmes, par exemple en échangeant des formats de date.

Enrichissement des données
Ajoute ou modifie des données dans votre message en appelant des services en cours de route. Par exemple, si un message contient un code postal, le bus peut utiliser un service de recherche de code postal pour ajouter des données d'adresse.

..et beaucoup, beaucoup plus. Lorsque vous commencez à regarder les détails, vous pouvez vraiment commencer à voir Pourquoi les gens utilisent ces choses.


13
2017-10-21 13:38



Parce que cela peut être une étape importante dans la manière de découpler les modules applicatifs architecture basée sur le service.

Donc dans votre cas, si vous n'avez pas l'intention de découpler les modules de votre application en services isolés, l'implémentation native du Motif d'observateur en fera une solution plus simple.

Mais si vous voulez construire, disons un architecture de micro-services le bus d'événements permettra d'obtenir les avantages de ce style d'architecture afin que vous puissiez, par exemple, mettre à jour et déployer certaines parties de votre application sans affecter les autres, car elles sont simplement connectées via le bus d'événements.

Donc, la question principale est le niveau souhaité de découplage des composants applicatifs.

Quelques références à ce sujet:


3
2017-09-22 17:40



Une bonne analogie est celle d’un central téléphonique, où chaque combiné peut appeler tous les autres combinés. Un combiné compromis peut syntoniser d'autres conversations. Le contrôle du programme se déroule comme des fils (complexité cyclomatique de tous!). Ceci est similaire à la nécessité d'avoir une connexion / un support physique entre deux points d'extrémité. C'est donc pour N combinés au lieu d'avoir NC2 (logique combinatoire) flux pour chaque nouveau combiné, nous avons tendance à obtenir N flux.

Une réduction de la complexité implique un code facile à comprendre. Commençons par les points importants que vous avez mis en évidence: 1. Connaissance globale 2. Modifications intrusives.

Connaissances globales: Considérez l'événement de message comme une enveloppe. Du point de vue du gestionnaire d'événement / de l'expéditeur, aucune donnée n'est exposée et une enveloppe apparaît (sauf si une classe dérivée tente d'effectuer une inspection à l'aide des vérifications «instanceof»). Dans une bonne conception de la POO, cela ne se produirait jamais.

Modifications intrusives: Au lieu d'avoir une approche d'écouteur spécifique à un événement, on peut utiliser une approche globale de gestion des événements. En tant que tel, nous avons un type d'événement global (sur lequel les données sont sauvegardées et converties). Cela ressemble beaucoup au modèle PropertyBeanSupport en Java. Avec un seul type d'événement, nous devons avoir un seul type d'expéditeur et de type d'écoute. Cela implique que vous n'avez pas besoin de modifier le bus / les écouteurs chaque fois que vous voyez quelque chose de nouveau. La descente laide peut être apaisée en utilisant un modèle d'adaptateur (veuillez ne pas démarrer ce devis de redirection à un autre niveau!). Les programmeurs peuvent écrire l'assemblage dans n'importe quelle langue. Le besoin de bon sens et d'intelligence ne peut donc pas être substitué. Tout ce que j'ai l'intention de dire, c'est que cela peut être un outil efficace.

Les récepteurs d'événements réels peuvent facilement utiliser les écouteurs (composition / proxy). Dans une telle base de code Java, les écouteurs ressembleraient à des déclarations de classes internes autonomes (avec un avertissement inutilisé signalé dans certains IDE). Deux joueurs sur la plage jouent un jeu de balle, les joueurs ne réagissent pas avant de voir le ballon.

«@duffymo» souligne un autre aspect intéressant: «Un point de défaillance unique». Cela pourrait / pourrait en théorie affecter tout objet résidant en mémoire (RAM) et non spécifique à MessageHandlers.


1
2017-10-21 13:22



En guise d'exemple pratique, notre application synchronise avec un service Web tous les x nombre de minutes et, si de nouvelles données sont reçues, nous devons mettre à jour l'interface graphique. Maintenant que SyncAdapter s'exécute sur un thread d'arrière-plan, vous ne pouvez pas simplement pointer vers une vue de texte et modifier ses propriétés, vous devez créer un événement. Et le seul moyen de vous assurer que vous rencontrez cet événement est d'avoir un objet partagé (statique, singleton) transmettant cet événement aux abonnés.


0
2018-01-10 12:23