Czy uważa się za anty-wzorzec do czytania ze STDIN z biblioteki?

39

Podczas pisania biblioteki dla dużego projektu, nad którym pracuję w pracy, pojawił się problem, który wymagał wysłania tokena na adres e-mail, a następnie przesłania go z powrotem do kodu, z którego można go następnie wykorzystać.

Mój kolega mówi, że po prostu czytam ze STDIN (używając Pythona:), code = input("Enter code: ")a następnie przekazuję go użytkownikowi, jednak wydaje mi się, że jest to zła praktyka, ponieważ biblioteka może (w tym przypadku na pewno będzie) używana w zadaniu w tle na serwerze .

Zastanawiałem się, czy uznano to za anty-wzór, czy nie.

Paradoksy
źródło
45
Nie wszystko złe jest „anty-wzorem”, choć z pewnością jest złe.
Phoshi
4
„wzorzec” oznacza coś, co często robią programiści. To tylko anty-wzorzec, jeśli zarówno (A) jest złym pomysłem, jak i (B) czymś, co cały czas robią programiści.
Solomon Slow
20
Jest to zbyt głupie, aby być anty-wzorem. Anty-wzór jest czymś, co wydaje się naturalne i rozsądne, ale okazuje się złe, gdy się w niego zagłębisz. To, co tu opisujesz, jest oczywiście makabryczne.
Evan Harper
Nie widzę sensu żadnej z odpowiedzi. Celem ćwiczenia tokena użytkownika musi być udowodnienie, że adres e-mail użytkownika działa. Gdyby nie o to chodziło, o wiele łatwiej byłoby po prostu przechowywać token.
emory
2
To jest okropne. Jeśli przekazanie takiego tokena jest absolutnie wymagane, możesz utworzyć osobny plik wykonywalny za pomocą biblioteki i przekazać swój token na standardowe wejście. Ale porwanie standardowego pliku wykonywalnego wywołującego to nie-nie.
GrandmasterB

Odpowiedzi:

78

Zasadniczo biblioteki powinny być całkowicie odłączone od środowiska. Oznacza to, że nie powinni wykonywać operacji na standardowych strumieniach, określonych plikach ani mieć żadnych oczekiwań co do środowiska lub kontekstu, w którym są używane.

Oczywiście są wyjątki od tej reguły, ale musi być bardzo dobry powód. W przypadku używania stdinnie mogę znaleźć żadnego powodu (chyba że twoja biblioteka faktycznie udostępnia procedury do czytania ze standardowego wejścia, np. std::cinZ C ++). Ponadto wzięcie strumieni we / wy z parametru zamiast zakodowania ich na sztywno zapewnia tak dużą elastyczność, że nie warto tego robić.

Paul92
źródło
36
Wyjątkiem jest biblioteka, której konkretnym celem jest interakcja ze środowiskiem. Nawet wtedy szczegóły środowiska powinny zostać usunięte. Na przykład sterownik karty graficznej musi komunikować się z magistralą PCIe, ale identyfikator magistrali należy podać poprzez konfigurację.
Pomyślałem, że jest to wyjątek: mój pomysł był bliższy ncurses - ogólnie biblioteki interfejsu użytkownika w środowisku tekstowym. Jeśli jego celem jest odczytanie danych wejściowych użytkownika i dostarczenie danych wyjściowych, to dobry powód.
SF.
5
@SF. Nawet biblioteka taka jak ncurses powinna przyjmować jako argumenty parę deskryptorów plików, a nie kodować na stałe użycie 0 i 1. Możesz napisać program, w którym stdin i stdout mogą być przekierowywane, a zamiast tego chcesz otworzyć /dev/ttyw celu komunikacji z użytkownik. Program można nawet uruchomić bez terminala i otworzyć własny terminal za pomocą xterm -S.
kasperd
3
@kasperd: Najlepszym podejściem jest zapewnienie rozsądnych wartości domyślnych i możliwość ich zastąpienia.
SF.
1
W tym konkretnym przypadku nie widzę powodu, aby żądać strumienia jako danych wejściowych. Dlaczego nie zaakceptować tokena jako parametru?
jpmc26
16

Uznałbym, że niekoniecznie jest to anty-wzór, tylko źle zaprojektowana biblioteka. Pytanie o ciąg znaków jako parametr metody powinno być trywialne, w którym dane wejściowe mogłyby być przekazywane bezpośrednio do.

Jeśli to nie pasuje do tego zastosowania, parametrem metody może być strumień, z STDIN przekazanym do metody.

Jeśli to nie pasuje do tego zastosowania, biblioteka nie jest wystarczająco elastyczna.

Bryan Boettcher
źródło
4

Może warto rozważyć możliwość ustawienia w bibliotece wywołania zwrotnego do funkcji podanej przez użytkownika, która odczyta dane wejściowe z dowolnego miejsca , a następnie zwróci odpowiednią wartość z powrotem do dowolnej części biblioteki, która korzysta z tej funkcji.

FrustratedWithFormsDesigner
źródło
1

Jeśli odczytuje stdin, oznacza to, że chciałby przejąć własność stdin na poziomie programu. Prawdopodobnie nie jest kompatybilny z żadną inną biblioteką odczytującą ze standardowego, mniej szczegółowego protokołu dotyczącego sposobu ich wspólnego użytkowania. W moim osobistym glosariuszu uczyniłoby to bibliotekę ramową , co jest kosztownym kompromisem.

Ale w tym przypadku biblioteka powinna po prostu wziąć deskryptor pliku wejściowego.

djechlin
źródło
0

Odpowiedź @ Paul92 to dobra ogólna dyskusja, ale chciałbym zaoferować możliwe czyste (ish) rozwiązanie tego:

Biblioteka, ten kod musi być dostosowywany do dowolnego środowiska wykonawczego, więc nie można tak naprawdę poprosić STDINo jakiś kluczowy fragment danych. Po pierwsze, użytkownicy twojej biblioteki mogą nie mieć standardowego wejścia z wielu powodów. Zamiast tego możesz użyć jakiejś formy wzorca strategii , aby dostosować sposób odzyskiwania tokena.

W Pythonie prawdopodobnie najlepszą opcją jest przekazanie strategii pobierania tokena jako parametru funkcji. Coś w tym stylu:

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

Pomyśl o tym w ten sposób. Wymagany token jest argumentem funkcji bibliotecznej. Ponieważ wartość tokena może nie być statycznie znana w witrynie wywołującej, nie można tak naprawdę prosić o wartość jako argument. Zamiast tego, osoba dzwoniąca musi zapewnić funkcję, która będzie odpowiedzialna za dostarczenie tokena po wywołaniu.

Cała odpowiedzialność za podanie dokładnej mechaniki tokena jest teraz uzewnętrzniona z funkcji biblioteki. Odbiorca funkcji jest teraz odpowiedzialny za pozyskiwanie tokena za pomocą wszelkich dostępnych środków w czasie wykonywania. Może zapytać STDIN, ale może również działać jako brama pocztowa, czekać na wiadomość w skrzynce odbiorczej, czytać ją, wyodrębniać token i całkowicie zautomatyzować proces. Może to być okno dialogowe GUI lub formularz internetowy. Coś naprawdę - wszystkie opcje są teraz w rękach konsumenta biblioteki.

Roland Tepp
źródło