ライブラリ内からSTDINから読み取ることはアンチパターンと見なされますか?


39

私が仕事で取り組んでいる大規模なプロジェクトのライブラリを作成しているときに、トークンを電子メールアドレスに送信する必要があるという問題が発生し、その後コードに戻されてさらに使用できるようになりました。

私の同僚は(Pythonを使用してcode = input("Enter code: "))STDINから読み、それをユーザーに渡すように言っていますが、私にはライブラリがサーバー上のバックグラウンドタスクで使用される可能性があるため(この場合は間違いなく)、これは悪い習慣のようです。

これがアンチパターンと見なされるかどうか疑問に思っていました。


45
悪いことすべてが「アンチパターン」というわけではありませんが、これは確かに悪いことです。
Phoshi

4
「パターン」とは、プログラマが頻繁に行うことを意味します。(A)悪い考えであり、(B)開発者が常にやっていると思うものの両方である場合にのみ、アンチパターンです。
ソロモンスロー

20
これはあまりにも愚かなため、アンチパターンにはなりません。アンチパターンとは、自然で理にかなっているように見えますが、掘り下げると悪い結果になるものです。ここで説明しているのは、明らかに恐ろしいことです。
エヴァンハーパー

私は答えの要点を見ていません。ユーザートークンの練習のポイントは、ユーザーのメールアドレスが機能することを証明することです。それがポイントではない場合、トークンを単純に保存する方がはるかに簡単です。
エモリー

2
これはかなりひどいです。そのようなトークンを渡すことが絶対に必要な場合は、ライブラリを使用して別個の実行可能ファイルを作成し、トークンをそのstdinに渡すことができます。しかし、呼び出し実行可能ファイルの標準入力をハイジャックするには、それはノーです。
GrandmasterB

回答:


78

一般的なガイドラインとして、ライブラリは環境から完全に切断する必要があります。つまり、標準ストリームや特定のファイルに対して操作を実行したり、使用されている環境やコンテキストについて期待したりしないでください。

もちろん、この規則には例外がありますが、それには非常に正当な理由がなければなりません。を使用する場合stdin、私は理由を見つけることができません(ライブラリが実際にstd::cinC ++のようにstdinから読み込むためのルーチンを提供していない限り)。また、I / Oストリームをハードコーディングするのではなく、パラメーターから取得すると、柔軟性が非常に高くなるため、実行しない価値はありません。


36
例外は、環境と対話するという特定の目標を持つライブラリです。それでも、環境の詳細は抽象化する必要があります。たとえば、グラフィックスドライバーはPCIeバスと通信する必要がありますが、構成を介してバスIDを提供する必要があります。

これは私が考えた例外の一種です。私の考えはncursesに近いものでした。一般的には、テキスト環境のユーザーインターフェイスライブラリです。その目的がユーザー入力を読み取り、ユーザー出力を提供することである場合、それは正当な理由です。
SF。

5
@SF。以下のようにもライブラリのncursesは、引数としてファイルディスクリプタのペアを取るのではなくあなたがstdinとstdoutがリダイレクトすることができ、代わりに開きたいプログラム書きたいと思うかもしれません0と1を使用するハードコーディングする必要がある/dev/ttyと通信するためにはユーザー。プログラムは、端末なしで起動し、を使用して独自の端末を開くこともできますxterm -S
カスペルド

3
@kasperd:最良のアプローチは、適切なデフォルトとそれらをオーバーライドする機能を提供することです。
SF。

1
この特定のケースでは、入力としてストリームを要求する理由はありません。なぜトークンをパラメーターとして受け入れないのですか?
jpmc26

16

これは必ずしもアンチパターンではなく、不十分に設計されたライブラリだと思います。入力を直接渡すことができるメソッドパラメーターとして文字列を要求するのは簡単なはずです。

それがこの使用法に合わない場合、メソッドパラメータはストリームであり、STDINがメソッドに渡されます。

これがこの使用法に適合しない場合、ライブラリは十分な柔軟性を持ちません。


4

たぶんからの入力を読み込みますユーザー提供の関数へのコールバックを設定するには、ライブラリ内の能力を検討どこから、その機能を使用しているライブラリのどんな部分に適切な値の背中を返します。


1

stdinから読み取る場合は、stdinのプログラムレベルの所有権を取得することを意味します。標準入力から読み込む他のライブラリとは互換性がない可能性が高く、使用方法を共有するための具体的なプロトコルではありません。少なくとも私の個人的な用語集では、これはライブラリをフレームワークにしますが、これは高価なトレードオフです。

ただし、この場合、ライブラリはおそらく入力ファイル記述子のみを取る必要があります。


0

@ Paul92による答えは一般的な議論ですが、これに対して可能なクリーンな(ish)ソリューションを提供したいと思います。

ライブラリであるこのコードは、どのランタイム環境にも適応できる必要があるSTDINため、重要なデータを要求することはできません。1つには、ライブラリのユーザーがさまざまな理由で標準入力を利用できないことがあります。代わりに、何らかの形式の戦略パターンを使用して、トークンの取得方法をカスタマイズできます。

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ダイアログまたはWebベースのフォームの場合があります。本当に何でも-すべてのオプションは現在、ライブラリの消費者の手にあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.