Quand les crochets sont-ils le bon choix de conception?


10

J'ai travaillé sur une grande application Rails où l'utilisation des rappels ActiveRecord était endémique et pénible. Sauvegarder un enregistrement a souvent eu des effets secondaires inattendus et c'était un défi de raisonner sur le système.

Dans le même temps, j'ai vu des hooks utilisés à bon escient dans le cadre de l'héritage (par exemple, une classe parent utilisant une méthode de modèle pour permettre aux sous-classes d'ajouter un comportement spécialisé sans avoir besoin de connaître les internes du parent), et dans les plug-ins (par exemple, un mode emacs exécutant un hook lorsqu'il est activé, permettant aux utilisateurs d'ajouter un comportement personnalisé autour de ce mode).

Je me rends compte qu'une application Rails et un interprète Lisp sont des systèmes très différents, mais je suis curieux de savoir s'il existe des critères bien connus auxquels les gens se tournent pour décider si les crochets sont le bon choix de conception pour le problème auquel ils sont confrontés.

Le thème qui me saute aux yeux est la prévisibilité. Une mauvaise utilisation des crochets semble entraîner une action effrayante à distance et un comportement surprenant, tandis qu'une bonne utilisation peut conduire à un cadre prévisible sans couplage serré.

Comme je ne suis encore que quelques années dans ma carrière en programmation, je me considère comme un noob à bien des égards, et les gens suspects ont réfléchi à ce sujet. Quelles sont les lignes directrices qui peuvent orienter cette décision?

Réponses:


5

Les crochets sont un bon choix de conception lorsque vous souhaitez dissocier les détails de mise en œuvre d'une abstraction de ses consommateurs en transférant le contrôle aux récepteurs du crochet.

Vous pouvez le faire par une diffusion anonyme (comme des événements ou des rappels anonymes), ou en utilisant des abstractions typées (comme des interfaces ou des classes parentes).

Vous devez utiliser la diffusion anonyme lorsque:

  • L'appel du crochet est facultatif
  • L'appelant ne se soucie pas de qui reçoit le crochet.
  • L'ordre d'exécution des récepteurs n'est pas pertinent.
  • Vous souhaitez diffuser l'état de l'objet à tous les abonnés au hook.

Vous devez utiliser une abstraction typée lorsque:

  • L'appel du crochet est obligatoire.
  • L'objet appelant doit identifier le récepteur du crochet.
  • L'ordre d'exécution des récepteurs est pertinent pour votre objet.

Un exemple de hook de diffusion est un événement KeyPressedEvent. La classe qui déclenche l'événement ne se soucie pas de qui le reçoit et diffuse l'état du clavier à toute personne abonnée à l'événement. L'ordre d'exécution des récepteurs n'a aucun effet sur l'état d'objet de la classe qui déclenche l'événement.

Un exemple de crochet d'abstraction typé est la méthode de modèle que vous avez mentionnée. Dans ce cas, la classe parente nécessite une implémentation pour ses méthodes de modèle, elle sait que les récepteurs en seront les enfants et elle a un ordre d'exécution spécifique pour les méthodes de modèle, tel que défini par la classe parente.


7

La plupart des langues et la plupart des plates-formes utilisent le hooking, même s'il est habillé comme autre chose. Chaque fois que vous entendez parler du terme "événement", "message", "déclencheur", "signal" ou d'autres termes de cette nature, vous avez probablement affaire à l'accrochage, bien qu'il existe des exceptions à la règle, qui ne le font probablement pas. question pour cette discussion.

Vous les utilisez parce que la plate-forme vous les fournit ou peut même nécessiter leur utilisation pour des raisons de performances. L'utilisation de crochets réduit souvent la complexité du code, aide à faire respecter les exigences de l'entreprise et réduit l'utilisation du processeur, prolongeant la durée de vie de la batterie et du matériel. Vous devez les utiliser chaque fois que vous voulez les meilleures performances de votre code.

Même votre expérience déchirante avec Rails identifie à peu près un cas d'utilisation courant pour les hooks: les règles métier doivent être appliquées, et les hooks sont à peu près universellement utilisés pour appliquer les règles métier. Malheureusement, toutes les règles n'ont pas de sens, et comme vous pouvez le constater, cela rend les choses plus difficiles pour un développeur lorsqu'elles sont arbitraires, mais c'est pourquoi la documentation d'un système est tout aussi importante que le code lui-même.

En règle générale, utilisez des hooks car ce sont des fonctionnalités de performance et rendront votre code plus efficace que l'alternative (qui est appelée "polling", où vous attendez dans une boucle occupée pour vérifier les événements). Cependant, assurez-vous également d'utiliser la documentation appropriée et de la maintenir à jour. Les crochets sont utilisés dans pratiquement toutes les langues que vous rencontrerez, et il est important de savoir pourquoi ils existent.


1

J'ai déjà travaillé sur un programme qui faisait selon moi une bonne utilisation des crochets. Dans mon livre, un vrai hook est un appel (publication) à une liste de rappels (abonnés). C'est puissant, l'abus est facile. La meilleure question à poser pour un cas d'utilisation est: est-ce que je veux activer ou désactiver le comportement lors de l'exécution? Par exemple, vous voudrez peut-être autoriser vos utilisateurs à fournir des scripts que vous exécuterez sur certains événements, ou créer un programme générique composé de plugins plus petits. Ensuite, les appels de raccordement sont appropriés. En général, vous avez peu d'autres options.

Sinon, vous devriez vous en sortir avec une bonne voûte de vos modules. Les méthodes de modèle fonctionnent bien avec les fonctions surchargées, vous n'avez pas besoin de logique d'exécution pour cela. Considérer que cela imposerait un couplage lâche est une illusion: il y a le même niveau de dépendance entre quelque chose que vous appelez directement ou que vous accrochez, l'appelé doit quand même remplir son contrat.

Notez que, peut-être que certaines personnes appellent la méthode modèle avec des fonctions surchargées, mais c'est différent de ce qui précède: ici, vous avez une liaison statique, avec un risque plus faible de tomber dans un cauchemar de maintenance.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.