web-dev-qa-db-fra.com

Est-il considéré comme un anti-modèle de lire depuis STDIN depuis une bibliothèque?

Lors de l'écriture d'une bibliothèque pour un grand projet sur lequel je travaille au travail, un problème est survenu qui a nécessité l'envoi d'un jeton à une adresse e-mail, puis le retour dans le code où il peut ensuite être utilisé pour une utilisation ultérieure.

Mon collègue dit de simplement lire à partir de STDIN (en utilisant Python: code = input("Enter code: ")) puis de demander à un utilisateur de le transmettre, mais cela me semble une mauvaise pratique car la bibliothèque pourrait (dans ce cas, certainement) être utilisée dans une tâche en arrière-plan sur un serveur.

Je me demandais si cela était ou non considéré comme un anti-modèle.

39
Paradoxis

En règle générale, les bibliothèques doivent être totalement déconnectées de l'environnement. Cela signifie qu'ils ne doivent pas effectuer d'opérations sur des flux standard, sur des fichiers spécifiques, ou avoir des attentes concernant l'environnement ou le contexte dans lequel ils sont utilisés.

Bien sûr, il existe des exceptions à cette règle, mais il doit y avoir une très bonne raison à cela. Dans le cas de l'utilisation de stdin, je ne trouve aucune raison (à moins que votre bibliothèque ne fournisse réellement des routines de lecture depuis stdin, comme std::cin de C++). En outre, la prise des flux d'E/S à partir d'un paramètre plutôt que leur codage en dur ajoute tellement de flexibilité que cela ne vaut pas la peine de ne pas le faire.

78
Paul92

Je considérerais que ce n'est pas nécessairement un anti-modèle, juste une bibliothèque mal conçue. Il devrait être trivial de demander une chaîne comme paramètre de méthode, où l'entrée pourrait être passée directement.

Si cela ne correspond pas à cette utilisation, un paramètre de méthode peut être un flux, avec STDIN passé dans la méthode.

Si cela ne correspond pas à cette utilisation, la bibliothèque n'est pas suffisamment flexible.

16
Bryan Boettcher

Peut-être envisagez-vous d'avoir la possibilité dans votre bibliothèque de définir un rappel vers une fonction fournie par l'utilisateur qui lira les entrées de partout, puis de renvoyer la valeur appropriée à la partie de la bibliothèque qui utilise cette fonction.

S'il lit depuis stdin, cela signifie qu'il souhaite s'approprier stdin au niveau du programme. Il n'est probablement pas compatible avec une autre bibliothèque qui lit à partir de stdin, un protocole moins spécifique pour la façon dont ils partagent l'utilisation. Dans au moins mon propre glossaire personnel, cela ferait de la bibliothèque un framework, ce qui est un compromis coûteux.

Mais dans ce cas, la bibliothèque devrait probablement prendre un descripteur de fichier d'entrée.

1
djechlin

La réponse de @ Paul92 est une bonne discussion générale, mais je voudrais proposer une solution propre (ish) à ceci:

En tant que bibliothèque, ce code doit être adaptable à n'importe quel environnement d'exécution, vous ne pouvez donc pas vraiment demander à STDIN des informations cruciales. D'une part, les utilisateurs de votre bibliothèque peuvent ne pas avoir stdin disponible pour un certain nombre de raisons. Au lieu de cela, vous souhaiterez peut-être utiliser une certaine forme de modèle de stratégie pour personnaliser la façon dont le jeton doit être récupéré.

En Python, la meilleure option est probablement de passer la stratégie de récupération de jeton en tant que paramètre de fonction. Quelque chose comme ca:

def stdin_Prompt():
    return input("Enter code: ")

def my_library_function(arg1, arg2, ... argn, token_provider = stdin_Prompt):
    ...
    token = token_provider()
    ...
    return stuff

# somewhere in the user code
stuff = my_library_function(a1, a2, ... an, lambda: "123456")

Pensez-y comme ça. Le jeton dont vous avez besoin est un argument de la fonction de bibliothèque. Étant donné que la valeur du jeton peut ne pas être connue statiquement sur le site d'appel, vous ne pouvez pas vraiment demander la valeur comme argument. Au lieu de cela, l'appelant doit fournir une fonction qui sera chargée de fournir le jeton lors de l'appel.

Toute la responsabilité de fournir la mécanique exacte du jeton est désormais externalisée à partir de la fonction de bibliothèque. Le consommateur de la fonction est désormais responsable de l'acquisition du jeton par tous les moyens disponibles au moment de l'exécution. Il peut demander à STDIN, mais il peut également agir comme une passerelle de messagerie, attendre que le message apparaisse dans la boîte de réception, le lire, extraire le jeton et automatiser complètement le processus. Il peut s'agir d'une boîte de dialogue GUI ou d'un formulaire Web. Rien de vraiment - toutes les options sont désormais entre les mains du consommateur de la bibliothèque.

0
Roland Tepp