web-dev-qa-db-ja.com

引数渡しの戦略-環境変数とコマンドライン

開発者が作成するほとんどのアプリケーションは、起動時に外部でパラメーター化する必要があります。ファイルパス、パイプ名、TCP/IPアドレスなどを渡します。これまでのところ、コマンドラインを使用して、起動中のアプリケーションにこれらを渡しています。私はmainのコマンドラインを解析して、引数を必要な場所に向ける必要がありました。もちろん、これは良いデザインですが、多数の引数に対して維持が難しい。最近、環境変数メカニズムを使用することにしました。それらはグローバルであり、どこからでもアクセスできます。つまり、アーキテクチャの観点からはあまりエレガントではありませんが、はコードの量を制限します

これらは両方の戦略に対する私の最初の(そしておそらくかなり浅い)印象ですが、より経験豊富な開発者の意見を聞きたいと思います-環境変数とコマンドラインを使用することの利点と欠点は何ですか引数をプロセスに渡すには?次の点を考慮したいのですが。

  1. 設計品質(柔軟性/保守性)、
  2. メモリ制約、
  3. ソリューションの移植性。

備考:

広告。 1.これは私が興味を持っている主要な側面です。

広告。 2.これは少し実用的です。現在 huge であるWindowsのいくつかの制限を知っています(コマンドラインと環境ブロックの両方で32kB以上)。必要であれば、ファイルを使用して大量の引数を渡す必要があるため、これは問題ではないと思います。

広告。 3. Unixについてはほとんど何も知らないので、両方の戦略がWindowsと同じように使用できるかどうかはわかりません。よろしければ、これについて詳しく説明してください。

73
Janusz Lenar

1)できるだけ環境変数を回避することをお勧めします。

環境変数の長所

  • どこからでも見えるので使いやすい。独立したプログラムの多くが情報を必要とする場合、このアプローチははるかに便利です。

環境変数の短所

  • どこからでも見える(削除可能、設定可能)ため、正しく使用するのは難しい。環境変数に依存する新しいプログラムをインストールすると、既存のプログラムを踏みにじるのですか?昨日見回りをしていたときに、環境変数をうっかり台無しにしたのでしょうか。

私の意見

  • プログラムの個々の呼び出しごとに異なる可能性が最も高い引数にコマンドライン引数を使用します(つまり、nを計算するプログラムの場合はn!)
  • ユーザーが合理的に変更したいがあまり頻繁ではない引数(つまり、ウィンドウがポップアップするときの表示サイズ)に設定ファイルを使用する
  • 環境変数の使用は控えめにしてください-変更されないと予想される引数(つまり、Pythonインタープリターの場所)に対してのみ使用することをお勧めします
  • あなたのポイント They are global and accessible from anywhere, which is less elegant from architectural point of view, but limits the amount of codeグローバル変数の使用の正当化を思い出させます;)

環境変数の酷使の恐怖を直接体験したことによる私の傷跡

  • 作業に必要な2つのプログラム。環境の衝突により、同じコンピューターで同時に実行することはできません。
  • 同じ名前でバグが異なるプログラムの複数のバージョン-プログラムの場所が環境から取得され、(静かに、微妙に)間違っていたため、ワークショップ全体が何時間もひざまずきました。

2)制限

コマンドラインが保持できるもの、または環境が処理できるもののいずれかの制限を押し進めていた場合、すぐにリファクタリングします。

過去には、多くのパラメーターを必要とするコマンドラインアプリケーションにJSONを使用しました。文字列や数値とともに、辞書やリストを使用できるのは非常に便利でした。アプリケーションはコマンドライン引数を2、3だけ取り、そのうちの1つはJSONファイルの場所でした。

このアプローチの利点

  • cLIライブラリとやり取りするために多くの(痛みを伴う)コードを記述する必要はありませんでした-複雑な制約を強制するために多くの共通ライブラリを取得するのは面倒です(「複雑な」とは、特定のキーまたはキーのセット間の代替)
  • 引数の順序に関するCLIライブラリーの要件について心配する必要はありません。JSONオブジェクトを使用するだけです!
  • 複雑なデータを簡単に表すことができます(回答What won't fit into command line parameters?)リストなど
  • 他のアプリケーションからのデータを使いやすい-プログラムで作成および解析するため
  • 将来の拡張に対応しやすい

:これを.config-fileアプローチと区別したい-これはユーザー設定を保存するためのものではありません。コマンドラインに適合しない多くの値を必要とするプログラムに使用するため、これを「コマンドラインパラメータファイル」アプローチと呼ぶ必要があるかもしれません。


3)ソリューションの移植性:Mac、PC、Linuxの環境変数とコマンドライン引数の違いについてはよくわかりませんが、次のように説明できます。

  • 3つすべてが環境変数をサポートしています
  • それらはすべてコマンドライン引数をサポートしています

はい、わかりました。あまり役に立ちませんでした。申し訳ありません。しかし、重要な点は、あなたがcanは、移植可能であることが合理的な解決策であると期待していることです。プラットフォーム?わからない)。


最後のポイント:

Tomaszが述べたように、パラメーターが由来するほとんどのアプリケーションでは問題になりません。

66
Matt Fenwick

Strategy パターンを使用して、読み取りパラメータを抽象化する必要があります。次の実装を使用して、readConfig(key) -> valueメソッドを持つ(またはConfigurationSourceオブジェクト/構造を返す)Configurationという名前の抽象化を作成します。

  • CommandLineConfigurationSource
  • EnvironmentVariableConfigurationSource
  • WindowsFileConfigurationSource-C:/Document and settings...の構成ファイルからロード
  • WindowsRegistryConfigurationSource
  • NetworkConfigrationSource
  • UnixFileConfigurationSource--/home/user/...から構成ファイルからロード
  • DefaultConfigurationSource-デフォルト
  • ...

チェーンの責任 パターンを使用して、次のようなさまざまな構成でソースをチェーンすることもできます。コマンドライン引数が指定されていない場合は環境変数を試し、それ以外がすべて失敗した場合はデフォルトを返します。

広告1.このアプローチでは、読み取り設定を抽象化できるだけでなく、クライアントコードに影響を与えることなく、基になるメカニズムを簡単に変更できます。また、一度に複数のソースを使用して、異なるソースから構成をフォールバックまたは収集することもできます。

広告2.適切な実装を選択するだけです。もちろん、一部の構成エントリは、たとえばコマンドライン引数に適合しません。

Ad 3.一部の実装が移植可能でない場合は、2つ用意してください。1つは、特定のシステムに適さない場合、黙って無視/スキップされます。

6

この質問にはすでにかなりの回答が出ていると思いますが、2018年の更新に値するものだと思います。環境変数の言及されていない利点は、一般に、作業に必要なボイラープレートコードが少なくて済むことです。これにより、コードがより読みやすくなります。ただし、大きな欠点は、同じマシンで実行されているさまざまなアプリケーションから分離のレイヤーが削除されることです。 Dockerが本当に素晴らしいのはこれだと思います。私のお気に入りの設計パターンは、環境変数のみを使用し、Dockerコンテナー内でアプリケーションを実行することです。これにより、分離の問題が解消されます。

3
mdornfe1