Quel est cet idiome «Exécuter autour» (ou similaire) dont j'ai entendu parler? Pourquoi pourrais-je l'utiliser et pourquoi pourrais-je ne pas vouloir l'utiliser?
java
language-agnostic
design-patterns
idioms
Tom Hawtin - Tacle
la source
la source
Réponses:
Fondamentalement, c'est le modèle dans lequel vous écrivez une méthode pour faire les choses qui sont toujours nécessaires, par exemple l'allocation et le nettoyage des ressources, et faites passer l'appelant "ce que nous voulons faire avec la ressource". Par exemple:
Le code d'appel n'a pas à se soucier du côté ouvert / nettoyage - il sera pris en charge par
executeWithFile
.C'était franchement pénible en Java car les fermetures étaient si verbeuses, à commencer par Java 8, les expressions lambda peuvent être implémentées comme dans de nombreux autres langages (par exemple les expressions C # lambda, ou Groovy), et ce cas particulier est géré depuis Java 7 avec
try-with-resources
etAutoClosable
streams.Bien que "allouer et nettoyer" soit l'exemple typique donné, il existe de nombreux autres exemples possibles - gestion des transactions, journalisation, exécution de code avec plus de privilèges, etc. C'est fondamentalement un peu comme le modèle de méthode de modèle mais sans héritage.
la source
L'idiome Execute Around est utilisé lorsque vous devez faire quelque chose comme ceci:
Afin d'éviter de répéter tout ce code redondant qui est toujours exécuté "autour" de vos tâches réelles, vous créeriez une classe qui s'en charge automatiquement:
Cet idiome déplace tout le code redondant compliqué en un seul endroit et laisse votre programme principal beaucoup plus lisible (et maintenable!)
Jetez un œil à cet article pour un exemple C # et cet article pour un exemple C ++.
la source
Une méthode Execute Around est l'endroit où vous passez du code arbitraire à une méthode, qui peut exécuter le code de configuration et / ou de démontage et exécuter votre code entre les deux.
Java n'est pas le langage dans lequel je choisirais de faire cela. Il est plus élégant de passer une fermeture (ou une expression lambda) comme argument. Bien que les objets soient sans doute équivalents à des fermetures .
Il me semble que la méthode Execute Around est un peu comme l' inversion de contrôle (injection de dépendance) que vous pouvez faire varier ad hoc, chaque fois que vous appelez la méthode.
Mais cela pourrait aussi être interprété comme un exemple de couplage de contrôle (indiquant à une méthode ce qu'il faut faire par son argument, littéralement dans ce cas).
la source
Je vois que vous avez une balise Java ici, je vais donc utiliser Java comme exemple même si le modèle n'est pas spécifique à la plate-forme.
L'idée est que parfois vous avez du code qui implique toujours le même passe-partout avant d'exécuter le code et après avoir exécuté le code. Un bon exemple est JDBC. Vous saisissez toujours une connexion et créez une instruction (ou une instruction préparée) avant d'exécuter la requête réelle et de traiter le jeu de résultats, puis vous effectuez toujours le même nettoyage standard à la fin - en fermant l'instruction et la connexion.
L'idée avec execute-around est qu'il vaut mieux que vous puissiez factoriser le code standard. Cela vous évite de taper, mais la raison est plus profonde. C'est le principe de ne pas se répéter (DRY) ici - vous isolez le code à un endroit, donc s'il y a un bogue ou si vous devez le changer, ou si vous voulez simplement le comprendre, tout est en un seul endroit.
La chose qui est un peu délicate avec ce type d'affacturage est que vous avez des références que les parties «avant» et «après» doivent voir. Dans l'exemple JDBC, cela inclurait la connexion et l'instruction (Prepared). Donc, pour gérer cela, vous "enveloppez" essentiellement votre code cible avec le code standard.
Vous connaissez peut-être certains cas courants en Java. L'un est les filtres de servlet. Un autre est AOP autour des conseils. Un troisième est les différentes classes xxxTemplate de Spring. Dans chaque cas, vous avez un objet wrapper dans lequel votre code "intéressant" (par exemple, la requête JDBC et le traitement de l'ensemble de résultats) est injecté. L'objet wrapper fait la partie "avant", invoque le code intéressant puis fait la partie "après".
la source
Voir aussi Code Sandwiches , qui examine cette construction dans de nombreux langages de programmation et propose des idées de recherche intéressantes. Concernant la question spécifique de savoir pourquoi on pourrait l'utiliser, le document ci-dessus offre quelques exemples concrets:
Et ensuite:
Le document n'explore pas pourquoi ne pas utiliser cet idiome, mais il décrit pourquoi il est facile de se tromper sans aide au niveau du langage:
la source
Je vais essayer d'expliquer, comme je le ferais à un enfant de quatre ans:
Exemple 1
Le Père Noël arrive en ville. Ses elfes codent ce qu'ils veulent derrière son dos, et à moins qu'ils ne changent les choses, ils deviennent un peu répétitifs:
Ou ca:
.... ad nauseam un million de fois avec un million de cadeaux différents: notez que la seule chose différente est l'étape 2. Si la deuxième étape est la seule chose qui est différente, alors pourquoi le Père Noël duplique-t-il le code, c'est-à-dire pourquoi duplique-t-il les étapes 1 et 3 un million de fois? Un million de cadeaux signifie qu'il répète inutilement les étapes 1 et 3 un million de fois.
Exécuter autour permet de résoudre ce problème. et aide à éliminer le code. Les étapes 1 et 3 sont fondamentalement constantes, ce qui permet à l'étape 2 d'être la seule partie qui change.
Exemple # 2
Si vous ne comprenez toujours pas, voici un autre exemple: pensez à un sandwhich: le pain à l'extérieur est toujours le même, mais ce qu'il y a à l'intérieur change en fonction du type de sable que vous choisissez (.eg jambon, fromage, confiture, beurre d'arachide, etc.). Le pain est toujours à l'extérieur et vous n'avez pas besoin de le répéter un milliard de fois pour chaque type de sable que vous créez.
Maintenant, si vous lisez les explications ci-dessus, vous trouverez peut-être plus facile à comprendre. J'espère que cette explication vous a aidé.
la source
Cela me rappelle le modèle de conception de la stratégie . Notez que le lien que j'ai indiqué inclut du code Java pour le modèle.
Évidemment, on pourrait effectuer "Execute Around" en faisant du code d'initialisation et de nettoyage et en passant simplement une stratégie, qui sera alors toujours enveloppée dans le code d'initialisation et de nettoyage.
Comme pour toute technique utilisée pour réduire la répétition du code, vous ne devriez pas l'utiliser avant d'avoir au moins 2 cas où vous en avez besoin, peut-être même 3 (selon le principe YAGNI). Gardez à l'esprit que la suppression de la répétition du code réduit la maintenance (moins de copies de code signifie moins de temps passé à copier les correctifs sur chaque copie), mais augmente également la maintenance (plus de code total). Ainsi, le coût de cette astuce est que vous ajoutez plus de code.
Ce type de technique est utile pour plus que l'initialisation et le nettoyage. C'est également utile lorsque vous souhaitez faciliter l'appel de vos fonctions (par exemple, vous pouvez l'utiliser dans un assistant afin que les boutons "suivant" et "précédent" n'aient pas besoin de déclarations de cas géantes pour décider quoi faire pour aller à la page suivante / précédente.
la source
Si vous voulez des idiomes groovy, voici:
la source