Habituellement, les écouteurs d'événements ne doivent pas survivre à l'objet qui les a enregistrés.
Cela signifie-t-il que les écouteurs d'événements doivent être détenus par des références faibles par défaut (stockées dans des collections faibles par les écouteurs d'objets enregistrés)?
Existe-t-il des cas valides où l'auditeur devrait survivre à son créateur?
Ou peut-être qu'une telle situation est une erreur et qu'elle ne devrait pas être autorisée?
api-design
event
mrpyo
la source
la source
Réponses:
Pourquoi les écouteurs d'événements ne devraient-ils pas survivre à l'objet qui les a enregistrés? Il semble que vous supposiez que les écouteurs d'événements devraient être enregistrés par des méthodes de contrôles (si nous prenons l'exemple de l'interface graphique) - ou plus précisément, des méthodes par des objets de classes qui héritent des contrôles de la boîte à outils de l'interface graphique. Ce n'est pas une nécessité - vous pouvez, par exemple, utiliser un objet spécialisé pour enregistrer les écouteurs d'événements et abandonner cet objet par la suite.
De plus, si les écouteurs d'événements sont faiblement référés, vous devrez en fait conserver des références même si vous n'utilisez jamais cette référence. Dans le cas contraire, l'auditeur sera collecté à un moment aléatoire. Nous obtenons donc un bug qui est
Et si éviter ce bug n'est pas une incitation suffisante, voici quelques autres:
Vous devrez penser à un nom pour chaque auditeur que vous créez.
Certaines langues utilisent une analyse statique qui génère un avertissement si vous avez un champ membre privé qui n'est jamais écrit ou jamais lu. Vous devrez utiliser un mécanisme pour remplacer cela.
L'auditeur d'événements fait quelque chose, et une fois que l'objet qui a sa référence forte est collecté, il cessera de faire ce quelque chose. Vous avez maintenant quelque chose qui affecte l'état du programme et dépend du GC - ce qui signifie que le GC affecte l'état concret du programme. Et c'est MAUVAIS !
La gestion des références faibles est plus lente, car vous avez un autre niveau d'indirection et puisque vous devez vérifier si la référence a été collectée. Ce ne serait pas un problème si avoir des écouteurs d'événements dans des références faibles était nécessaire - mais ce n'est pas le cas!
la source
En général, oui, des références faibles doivent être utilisées. Mais d'abord, nous devons être clairs sur ce que vous entendez par «auditeurs d'événements».
Rappels
Dans certains styles de programmation, en particulier dans le contexte des opérations asynchrones, il est courant de représenter une partie d'un calcul comme un rappel qui est exécuté sur un certain événement. Par exemple, un
Promise
[ 1 ] peut avoir unethen
méthode qui enregistre un rappel à la fin de l'étape précédente:Ici, les rappels enregistrés par
then
doivent être tenus par des références fortes, car la promesse (la source de l'événement) est le seul objet contenant une référence au rappel. Ce n'est pas un problème car la promesse elle-même a une durée de vie limitée et sera récupérée après la fin de la chaîne de promesses.Modèle d'observateur
Dans le modèle d'observateur, un sujet a une liste d'observateurs dépendants. Lorsque le sujet entre dans un état, les observateurs sont avertis selon une certaine interface. Des observateurs peuvent être ajoutés et supprimés du sujet. Ces observateurs n'existent pas dans un vide sémantique, mais attendent des événements dans un certain but.
Si cet objectif n'existe plus, les observateurs doivent être retirés du sujet. Même dans les langues récupérées, cette suppression peut devoir être effectuée manuellement. Si nous ne parvenons pas à retirer un observateur, il sera maintenu en vie via la référence du sujet à l'observateur, et avec lui tous les objets auxquels l'observateur fait référence. Cela gaspille de la mémoire et dégrade les performances car l'observateur (désormais inutile) sera toujours averti.
Les références faibles corrigent cette fuite de mémoire, car elles permettent à l'observateur d'être récupéré. Lorsque le sujet se déplace pour avertir tous les observateurs et constate qu'une des références faibles à un observateur est vide, cette référence peut être supprimée en toute sécurité. Alternativement, les références faibles peuvent être implémentées de manière à permettre au sujet d'enregistrer un rappel de nettoyage qui supprimera l'observateur lors de la collecte.
Mais notez que les références faibles ne sont qu'un pansement qui limite les dégâts en oubliant de retirer un observateur. La bonne solution serait de s'assurer qu'un observateur est retiré lorsqu'il n'est plus nécessaire. Les options comprennent:
Le faire manuellement, mais cela est sujet à des erreurs.
Utiliser quelque chose qui ressemble à essayer avec des ressources en Java ou
using
en C #.Destruction déterministe, par exemple via l'idiome RAII. Notez que dans un langage avec un ramasse-miettes déterministe, cela pourrait encore nécessiter de faibles références du sujet à l'observateur afin de déclencher le destructeur.
la source