it-swarm.com.de

Wird es als Anti-Pattern angesehen, aus STDIN aus einer Bibliothek heraus zu lesen?

Beim Schreiben einer Bibliothek für ein großes Projekt, an dem ich gerade arbeite, trat ein Problem auf, bei dem ein Token an eine E-Mail-Adresse gesendet und dann an den Code zurückgegeben werden musste, wo es für die weitere Verwendung verwendet werden kann.

Mein Kollege sagt, er solle nur aus STDIN lesen (mit Python: code = input("Enter code: ")) und dann von einem Benutzer übergeben lassen. Für mich scheint dies jedoch eine schlechte Praxis zu sein, da die Bibliothek möglicherweise (in diesem Fall definitiv) verwendet wird in einer Hintergrundaufgabe auf einem Server.

Ich habe mich gefragt, ob dies als Anti-Muster angesehen wird oder nicht.

39
Paradoxis

Als allgemeine Richtlinie sollten Bibliotheken vollständig von der Umgebung getrennt werden. Das bedeutet, dass sie keine Vorgänge für Standard-Streams oder für bestimmte Dateien ausführen oder Erwartungen an die Umgebung oder den Kontext haben sollten, in dem sie verwendet werden.

Natürlich gibt es Ausnahmen von dieser Regel, aber es muss einen sehr guten Grund dafür geben. Im Fall der Verwendung von stdin kann ich keinen Grund finden (es sei denn, Ihre Bibliothek bietet tatsächlich Routinen zum Lesen von stdin wie std::cin aus C++). Wenn Sie die E/A-Streams von einem Parameter übernehmen, anstatt sie fest codieren zu lassen, wird so viel Flexibilität hinzugefügt, dass es sich nicht lohnt, dies nicht zu tun.

78
Paul92

Ich würde dies nicht unbedingt als Anti-Pattern betrachten, sondern nur als schlecht gestaltete Bibliothek. Es sollte trivial sein, nach einem String als Methodenparameter zu fragen, in den die Eingabe direkt übergeben werden kann.

Wenn dies nicht zu dieser Verwendung passt, kann ein Methodenparameter ein Stream sein, wobei STDIN an die Methode übergeben wird.

Wenn dies nicht zu dieser Verwendung passt, ist die Bibliothek nicht flexibel genug.

16
Bryan Boettcher

Möglicherweise möchten Sie in Ihrer Bibliothek einen Rückruf für eine vom Benutzer bereitgestellte Funktion festlegen, die Eingaben von wo auch immer liest, und dann den entsprechenden Wert an den Teil der Bibliothek zurückgeben, der diese Funktion verwendet.

Wenn es von stdin liest, bedeutet dies, dass es stdin auf Programmebene übernehmen möchte. Es ist wahrscheinlich nicht kompatibel mit einer anderen Bibliothek, die aus einem weniger spezifischen Standardprotokoll für die gemeinsame Nutzung liest. Zumindest in meinem persönlichen Glossar würde dies die Bibliothek zu einem Framework machen, was ein teurer Kompromiss ist.

In diesem Fall sollte die Bibliothek jedoch wahrscheinlich nur einen Eingabedateideskriptor verwenden.

1
djechlin

Die Antwort von @ Paul92 ist eine gute allgemeine Diskussion, aber ich möchte eine mögliche clean (ish) Lösung dafür anbieten:

Als Bibliothek muss dieser Code an jede Laufzeitumgebung anpassbar sein, damit Sie STDIN nicht wirklich nach wichtigen Daten fragen können. Zum einen steht Benutzern Ihrer Bibliothek aus verschiedenen Gründen möglicherweise kein Standard zur Verfügung. Stattdessen möchten Sie möglicherweise eine Form von Strategie Muster verwenden, um anzupassen, wie das Token abgerufen werden soll.

In Python ist es wahrscheinlich die beste Option, die Token-Abrufstrategie als Funktionsparameter zu übergeben. So ähnlich:

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")

Stellen Sie sich das so vor. Das von Ihnen benötigte Token ist ein Argument für die Bibliotheksfunktion. Da der Wert für das Token am Aufrufstandort möglicherweise nicht statisch bekannt ist, können Sie den Wert nicht wirklich als Argument anfordern. Stattdessen muss der Anrufer eine Funktion bereitstellen, die für die Bereitstellung des Tokens beim Aufruf verantwortlich ist.

Die gesamte Verantwortung für Bereitstellung der genauen Mechanik des Tokens wird jetzt von der Bibliotheksfunktion ausgelagert. Der Benutzer der Funktion ist nun dafür verantwortlich, das Token mit allen zur Laufzeit verfügbaren Mitteln zu erwerben. Es kann STDIN fragen, aber es kann auch als Mail-Gateway fungieren, warten, bis die Nachricht im Posteingang eingeht, sie lesen, das Token extrahieren und den Prozess vollständig automatisieren. Dies kann ein GUI-Dialog oder ein webbasiertes Formular sein. Alles wirklich - alle Optionen liegen jetzt in den Händen des Bibliothekskonsumenten.

0
Roland Tepp