Чи вважається анти-зразком читати STDIN з бібліотеки?


39

Під час написання бібліотеки для великого проекту, над яким я працюю на роботі, виникла проблема, яка вимагала надсилання маркера на електронну адресу, а потім повернення назад у код, де він може бути використаний для подальшого використання.

Мій колега каже просто прочитати з STDIN (використовуючи Python:), code = input("Enter code: ")а потім дозволити користувачу передати його, проте мені це здається поганою практикою, оскільки бібліотека (у цьому випадку, безумовно, буде використана) у фоновому завданні на сервері .

Мені було цікаво, вважають це чи не анти-зразком чи ні.


45
Не все погане - це «анти-модель», хоча це, звичайно, погано.
Phoshi

4
"шаблон" означає те, що часто роблять програмісти. Це лише анти-візерунок, якщо це і (А) погана ідея, і (В) те, що ви бачите розробникам постійно.
Соломон повільно

20
Це занадто глупо, щоб бути анти-зразком. Антидіаграма - це щось, що здається природним і розумним, але виявляється поганим, коли ви копаєтеся в ньому. Те, що ви тут описуєте, просто очевидно жахливе.
Еван Харпер

Я не бачу сенсу жодної з відповідей. Суть вправника маркера користувача повинна полягати в тому, щоб довести, що електронна адреса користувача працює. Якби це не суть, то набагато простіше просто зберігати маркер.
emory

2
Це досить жахливо. Якщо передача такої лексеми абсолютно необхідна, ви можете зробити окремий виконуваний файл за допомогою бібліотеки та передати маркер його stdin. Але захоплювати stdin виклику, який виконується, це ні-ні.
гросмайстерB

Відповіді:


78

Як загальне керівництво, бібліотеки повинні бути повністю відключені від навколишнього середовища. Це означає, що вони не повинні виконувати операції над стандартними потоками, над певними файлами або очікувати щодо середовища чи контексту, яким вони користуються.

Звичайно, з цього правила є винятки, але це має бути дуже вагома причина. У випадку використання stdinя не можу знайти жодної причини (якщо тільки ваша бібліотека фактично не пропонує підпрограми для читання з stdin, як, наприклад, std::cinз C ++). Крім того, прийом потоків вводу / виводу з параметра, а не їх жорстке кодування, додає стільки гнучкості, що робити це не варто.


36
Виняток становить бібліотека, яка має конкретну мету взаємодії з оточенням. Вже тоді деталі довкілля слід абстрагувати. Наприклад, графічний драйвер повинен спілкуватися з шиною PCIe, але ідентифікатор шини повинен бути наданий через конфігурацію.

Це такий виняток, про який я думав: моя ідея була ближчою до ncurses - загалом, бібліотеки користувальницького текстового середовища інтерфейсу. Якщо його мета полягає в тому, щоб прочитати введення користувача та надати користувачеві вихід, це вагома причина.
СФ.

5
@SF. Навіть бібліотека, як ncurses, повинна брати пару дескрипторів файлів як аргументи, а не жорстке кодування з використанням 0 і 1. Можливо, ви хочете написати програму, де stdin та stdout можна переспрямовувати, а замість цього ви хочете відкрити /dev/ttyдля спілкування з користувач. Програму можна навіть запустити без терміналу і відкрити власний термінал за допомогою xterm -S.
kasperd

3
@kasperd: Найкращий підхід - це надання розумних значень за замовчуванням та можливість їх зміни.
СФ.

1
У цьому конкретному випадку я не бачу причин вимагати потоку як введення. Чому б просто не прийняти маркер як параметр?
jpmc26

16

Я вважав би це не обов'язково анти-шаблоном, а лише погано розробленою бібліотекою. Слід запитати рядок як параметр методу, де вхід може бути переданий безпосередньо в.

Якщо це не відповідає цьому використанню, то параметром методу може бути потік, при цьому STDIN передається в метод.

Якщо це не відповідає такому використанню, то бібліотека недостатньо гнучка.


4

Можливо, подумайте про можливість у вашій бібліотеці встановити зворотний дзвінок на функцію, надану користувачем, яка буде читати вхід звідки завгодно , а потім повертати відповідне значення назад у ту частину бібліотеки, яка використовує цю функцію.


1

Якщо він читає з stdin, це означає, що він хотів би взяти на себе програмне право власності на stdin. Це, ймовірно, не сумісне з будь-якою іншою бібліотекою, яка читає зі stdin, менш специфічний протокол того, яким чином вони використовують спільне використання. Принаймні мій власний особистий словник, це зробить бібліотеку основою , що є дорогим компромісом.

Але в цьому випадку бібліотека, ймовірно, повинна просто брати дескриптор вхідного файлу.


0

Відповідь @ Paul92 - це хороша загальна дискусія, але я хотів би запропонувати можливе чисте рішення для цього:

Бібліотека, цей код повинен бути пристосований до будь-якого середовища виконання, тому ви не можете дійсно запитувати STDINякийсь важливий біт даних. З однієї причини, користувачі вашої бібліотеки можуть бути недоступними з кількох причин. Натомість ви можете скористатись якоюсь формою стратегії, щоб налаштувати спосіб отримання маркера.

У Python, мабуть, найкращим варіантом є передача стратегії отримання токена як параметр функції. Щось схоже:

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

Подумайте про це так. Маркер, який вам потрібен, є аргументом функції бібліотеки. Оскільки значення маркера може бути статично не відомим на сайті виклику, ви не можете насправді запитувати значення як аргумент. Натомість абонент повинен надати функцію, яка буде відповідати за надання маркера при виклику.

Вся відповідальність за надання точної механіки маркера тепер покладається на функцію бібліотеки. Споживач функції тепер несе відповідальність за придбання маркера будь-якими способами, доступними під час виконання. Він може запитати STDIN, але він може також виконувати функцію поштового шлюзу, зачекайте, поки повідомлення з’явиться у папці "Вхідні", прочитайте його, витягніть маркер і повністю автоматизуйте процес. Це може бути діалог GUI або веб-форма. Все, що насправді - усі варіанти зараз у руках споживача бібліотеки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.