web-dev-qa-db-fra.com

Terme (ou "modèle"?) Pour "Faire quelque chose si ce n'est pas déjà fait"

Cela semble assez basique, je sais, mais un collègue m'a récemment dit qu'une méthode appelée startHttpServer est trop compliquée à comprendre car elle ne démarre le serveur que s'il n'est pas déjà en cours d'exécution. Je trouve que j'ai des ennuis quand je réponds: "Sérieusement? Je fais ça depuis des décennies - c'est un modèle courant en programmation." Plus souvent que je ne veux l'admettre, il revient avec des preuves documentées qui montrent que toute la communauté de la programmation est derrière son point de vue et je finis par me sentir penaud.

Question: Existe-t-il un modèle de conception documenté derrière le concept d'une méthode qui ne fonctionne pas si l'action requise est déjà en vigueur? Ou, si ce n'est pas un modèle, a-t-il un nom non plus? Et sinon, y a-t-il une raison de penser qu'il est trop compliqué d'envisager d'écrire une méthode de cette manière?

54
John Calcote

Comme NickWilliams l'a déjà dit : le concept décrit par l'OP est appelé idempotent (nom Idempotence ). C'est en effet une pratique courante, notamment dans les API de haut niveau.

MAIS: Renommez la fonction.

Au lieu de startHttpServer appelez-le makeSureHttpServerIsRunning ou ensureHttpServerIsRunning.

Lorsqu'une fonction est appelée startHttpServer, les lecteurs s'attendent à ce qu'elle démarre un serveur HTTP; lorsqu'il est appelé dix fois de suite, j'ai dix serveurs en cours d'exécution. Votre fonction ne le fait pas la plupart du temps. De plus, le nom avec "start" suggère que si je veux qu'un seul serveur fonctionne, je devrai savoir si la fonction a déjà été appelée ou non.

Lorsqu'une fonction est appelée makeSureHttpServerIsRunning, je suppose qu'elle fera les choses nécessaires pour s'assurer qu'un serveur HTTP fonctionne, probablement en vérifiant s'il est déjà en cours d'exécution et en le démarrant autrement. Je suppose également que la fonction s'assure que le serveur fonctionne réellement (le démarrage d'un serveur peut impliquer un certain temps où il ne fonctionne pas encore tout à fait).

127
gnasher729

Renommez-le en EnsureServerRunning.

Complètement sans ambiguïté et il est clair qu'il s'assure qu'il fonctionne (s'il ne l'est pas) sans impliquer un redémarrage s'il l'est.

(Alternative: StartServerIfNotRunning?)

33
Stilez

Pas vraiment un modèle de conception, mais j'appellerais votre méthode idempotente . Ce terme est généralement utilisé pour faire référence aux appels à distance, mais la description semble correspondre à ce que vous faites.

Méthodes idempotentes. Les méthodes peuvent également avoir la propriété "idempotence" en ce que (à part les problèmes d'erreur ou d'expiration) les effets secondaires de N> 0 requêtes identiques sont les mêmes que pour une seule requête. ( De W3.org )

L'effet secondaire du serveur ici est que le serveur http est démarré une fois la méthode appelée. Je ne vois rien de mal à une méthode faisant cela.

Si vous avez besoin d'un modèle de conception, je suppose que vous pouvez exposer votre httpServer comme un singleton qui est démarré lors de l'initialisation.

29
Nick Williams

En tant que celui qui implémente cet outil , startHttpServer, vous devriez essayer de le rendre le plus simple, fluide et transparente à utiliser ...

La logique de la fonction

Techniquement, en divisant la logique de startHttpServer en 2 fonctions et en les appelant séparément , tout ce que vous faites est de déplacer startHttpServeridempotency dans le code appelant les deux fonctions à la place ... De plus, à moins que vous n'encapsuliez les deux logiques dans une troisième fonction (c'est ce que fait startHttpServer en premier lieu), cela vous oblige à écrire du code non SÉCHÉ, en le dupliquant de façon exponentielle partout où vous devriez appeler startHttpServer. En bref, startHttpServer doit s'appeler la fonction isHttpServerRunning.

Mon point est donc:

  • Implémentez la fonction isHttpServerRunning car cela peut être nécessaire indépendamment de toute façon ...
  • Implémentez startHttpServer en utilisant isHttpServerRunning pour définir sa prochaine action en conséquence ...

Néanmoins, vous pouvez faire en sorte que startHttpServer retourne toute valeur dont l'utilisateur de cette fonction pourrait avoir besoin, par exemple:

  • 0 => échec de démarrage du serveur
  • 1 => démarrage réussi du serveur
  • 2 => le serveur a déjà démarré

Dénomination de la fonction

Tout d'abord, quel est l'objectif principal de l'utilisateur? Pour démarrer le serveur HTTP, non?

Fondamentalement, il n'y a aucun problème à vouloir démarrer quelque chose qui a déjà commencé, AKA 1*1=1. Donc, au moins pour moi, l'appeler "ensureHttpServerIsRunning" ne semble pas indispensable, je me soucierais plus de la durée, de la nature et de la mémorisation du nom de la fonction.

Maintenant, si vous voulez savoir comment fonctionne en détail la fonction sous le capot, il y a la documentation ou la source de code pour cela, je veux dire comme pour toute autre fonction de bibliothèque/framework/API/etc ...

Vous apprenez la fonction une fois pendant que vous écrivez plusieurs fois ...

Donc, de toute façon, je resterais avec startHttpServer qui est plus court, plus simple et plus explicite que ensureHttpServerIsRunning.

7
ClemC

Puisque vous ne spécifiez pas de langue, en JavaScript, de nombreuses bibliothèques ont une fonction "une fois" par exemple, Underscore . Donc, si cela vous est familier, appelez-le un modèle "une fois" et renommez éventuellement votre méthode.

Moi, venant plus de Java, les termes "mise en cache" ou "évaluation paresseuse" me viennent à l'esprit. "Idempotent" est techniquement correct et un bon choix, en particulier. si vous avez un parcours plus fonctionnel.

2
user949300

Je suppose que votre collègue voulait dire que startHttpServer en faisait trop:

  • Vérifier si le serveur est déjà en cours d'exécution,
  • Démarrage du serveur si nécessaire.

Ce sont deux parties indépendantes du code. Par exemple, une situation similaire existe lorsqu'une application de bureau doit s'assurer qu'elle n'est pas déjà en cours d'exécution lorsqu'elle est lancée; il y aura une partie du code qui gère les instances d'application (par exemple en utilisant un mutex), et le code qui démarrera la boucle de message de l'application.

Cela signifie que vous devez avoir non pas une, mais au moins¹ deux méthodes:

  • isHttpServerRunning: boolean
  • startHttpServer

Le point d'entrée de l'application appellera la première méthode, puis la seconde si la valeur de retour est false. Maintenant, chaque méthode fait une chose et est facile à comprendre.


¹ Si la logique nécessaire pour savoir si le serveur est déjà en cours d'exécution est trop complexe, elle peut nécessiter une séparation supplémentaire en plusieurs méthodes.

2
Arseni Mourzenko