シミュレーションを実行するコマンドラインアプリケーションに取り組んでいます。高度に構成可能である必要があります。ユーザーは、非常に多数(100以上)のパラメーターを提供できる必要があります。一部は必須で、一部はオプションです。明らかに、これらのパラメーターは、アプリケーションのさまざまなクラスで使用されます。
使用できる2つのアプローチがわかります。長期的にはどちらが優れたデザインですか?
アプローチ1
(テキスト)入力ファイルで、アプリケーションでのオブジェクトの作成を直接制御します。たとえば、ユーザーは次の入力を提供します。
_root=Simulation
time=50
local_species=Sentient
strength=3.5
intelligence=7.1
invading_species=Primitive
strength=5.1
sociability=2.6
_
次に、アプリケーションは、等号のrhsで指定されたクラスのオブジェクトを再帰的に作成し、クラスのコンストラクターに、入力ファイルの関連するサブブランチで提供された引数がある場合はそれを渡します。私はPythonを使用しています。これは、引数が指定されていない場合にキーワード引数とデフォルトの引数値をサポートしますが、質問がひどく言語固有ではないことを願っています。
たとえば、1行目は、3つのコンストラクター引数を使用して_class Simulation
_のオブジェクトを作成するようにアプリに指示します。最初のコンストラクター引数は_time=50
_です。 2番目の引数は_class Sentient
_のインスタンスであり、Simulation
のコンストラクター引数_strength=3.5
_、_intelligence=7.1
_を渡すことによって作成されます。 3番目の引数は_class Primitive
_のインスタンスであり、コンストラクター引数_strength=5.1
_、_sociability=2.6
_を渡すことによって作成されます。
オブジェクトの作成全体は、数行の(再帰的な)コードで自動的に処理されます。最高レベルのオブジェクト(この場合はSimulation
のインスタンス)が視覚化レイヤーに渡されます。
アプローチ2
入力ファイルは同じように見えます。ただし、アプリケーションのクラスは、ユーザー入力の解釈方法を完全に制御できるようになりました。 lhsとrhsの値は、キーワードのパラメーターとクラスに対応する場合と対応しない場合があります。たとえば、上記の入力により、アプリケーションは引数_class InvasionSimulation
_、_strength_local=3.5
_、_intelligence_local=7.1
_、_strength_invading=5.1
_を使用して_sociability_invading=2.6
_のインスタンスを作成し、メソッドset_runtime(time=50)
、オブジェクトを視覚化レイヤーに渡す前。
アプローチ2の明らかな利点の1つは、アプリケーションが内部で完全に再設計された場合でも、ユーザーの入力が安定していることです。しかし、クラスのサブセットを「パブリックAPI」として指定し、それによって将来変更されないようにすることには何の問題もないと思いますか?
一方、アプリケーションがとにかくアプローチ1と非常によく似たものに従う場合、アプローチ2では多くの冗長コードを追加する必要があると感じます。ユーザー入力を自動的に解釈するのではなく、それぞれに対して「手動で」行う必要があります。クラス。
追加の考慮事項があれば大歓迎です。私が検索できるこれらのアプローチの名前はありますか?
JAXB(Javaおよびxml構成))またはJSONマッパー(JSON構成)(空白の数が多い言語は好きではありませんが、それは個人的なものです)のようなものを使用しますまたは、好み/強制フォーマット用の他のマッパー。
これにより、アプリケーション内で必要なものと一致する場合はマップされたオブジェクトを使用し(アプローチ1)、一致しない場合はファクトリメソッドのパラメーターとして使用するため(アプローチ2と同様)、テキストソースの形式は重要ではありません。ロード中のコンテンツのみ。これにより、それらのファイルの読み取り以外は何も変更せずに、複数の入力形式を使用できます。
アプローチ1が有望に見えたら、後でリファクタリングすることから始めます。
私の個人的な経験では、コマンドまたは構成引数をコマンドラインプログラムに取り込むための唯一の最良のアプローチは辞書です。入力は自然にキーと値のペアとして構造化されるため、入力の観点からは意味がありますが、パーサーがすべてを辞書にプルするだけなので、新しいキーハンドラーを追加するだけで、新しい解析コードを追加する必要がない場合の保守性が向上します。必要なキーは何でも。また、引数スペースのコンシューマーにスコープを強制することはないため、各引数と値は、関連性があると感じるすべてのコンシューマーがデフォルトで使用できます。引数と値をコンシューマーに公開するために足を運ぶ必要はありません。
さらに、引数に対応するキーのリストと、それらのキーの構成が必要な限り、これらのキーを解析および処理する関数である値のリストを含む、mainで使用可能な辞書を最初に作成する習慣がありました。処理が行われる前のシステム状態。たとえば、vのキーには、その引数キーの値を解析して_System.Verbosity = true;
_を設定する関数があり、引数パーサーは_startupDictionary[argument](value);
を呼び出すだけで、関数がfalseを返した場合、それは引数が無効または無効な引数があったため、このようにして、使用可能な引数のセットが与えられた場合にシステム状態が不整合になり、したがって正しく処理できないことを引数パーサーに通知する場合があります。