2012-01-02 9 views
0

私は、多くの場合、オブジェクト設計のためにこれらの2つの方法の間で決定する必要があります。OOPの初期化戦略

  1. 完全に初期化し、その構築後に使用する準備ができているオブジェクト。コンストラクタは複雑なパラメータリストを必要とすることが多いため、オブジェクトの初期化は重要ではありません。それをメンバ変数として持つすべてのオブジェクトには、他に類のないコンストラクタも必要です。これは、オブジェクトコンストラクタに複雑さが集中しているコードにつながり、コードを追従しにくくすることがあります。
  2. デフォルトのコンストラクタを持つオブジェクトです。オブジェクト変数はsetter methodsによって個別に設定されます。このアプローチは、ほとんどのメソッドがオブジェクトが完全に初期化されているかどうかをチェックする必要があり、コードが複雑になるという欠点があります。

あなたの個人的な好みは何ですか?また、どちらを使用するかはどのように決定しますか?

答えて

2

私の意見では、コンストラクタがあまりにも肥大化している場合は、より多くの異なるオブジェクトでオブジェクトを分割する時間です。これはまれなケースでは不可能かもしれませんが、ほとんどの場合、実行できます。

-1

コンストラクタ内のすべての変数を初期値にするのは良いことですが、デフォルト値にすることは常に役に立ちます。変数の値を取得することが困難な場合(たとえば、その値を取得するために関数を呼び出す必要があるなど)、その値を無効な値に設定してから、後で正しい値を設定することができます。

コンストラクタでエラーを返すことができないので、コンストラクタを非常に複雑にすることはお勧めできません(コンストラクタで例外をスローするかどうかわかりません。特にどこでもtrhowing例外は好きではない)。また、そこに仮想関数を呼び出すことはできません。

私が気に入っているアプローチは、クラスの構築が複雑なときに "init"関数を作成することです。それで、私は次のようなことをすることができます:

などです。

+0

-1あなたのctorを2つの部分(ctor自体と 'Init')に分割するための-1。 IMHOこれは、コンストラクタが意味するものとは逆です:オブジェクトを有効な状態にする。確かに、ctorはあまり多くの作業を行うべきではないので、 'age'の値を簡単に決めることができない場合は、' functor 'オブジェクトをctorに渡します。後で呼び出されると 'age' 。おそらく、このような方法に賛成して「年齢」を完全に削除することさえできます。しかし、もう一つの義務的な 'Init'メソッドを導入してはいません。これは実際にはctorの単なる継続です。 (そして、 "魔法"の戻り値の代わりに例外を使用してください。) – stakx

+0

(例えば、 'functionThatReturnsTheAgeFromSomeDB'を、オブジェクトメソッドに渡されたファクトリメソッドに置き換えることの追加ボーナスは、あなたがいくつかのDBの隠された依存関係を取り除くことです。より透過的でテストしやすくなります。) – stakx

+0

JSF ++やMisraなどの多くの安全上重要なコーディング標準では、例外の使用を避けています。とにかく、 "Init"関数を使いたくない場合は、なぜ例外の使用法を提案していますか?コンストラクターの例外で彼は何をしますか?コンストラクターは例外を発生させることができないので、それは "init"関数を持つもう一つの理由です。 –

2

コンストラクタは—あなたはこの非自明なオブジェクトの初期化—を呼び出し、あなたは小さなものにあなたのクラスを分割したくない多くの引数を取る場合は、一つの代替がParameter Objectにパラメータを入れた後、唯一渡すことですそのオブジェクトをコンストラクタに渡します。

第二には、私はあなたがオブジェクトがその作業を行うことになっている場合は絶対に設定する必要があります

    • ...間のオブジェクトのプロパティを区別する必要があることを信じて、そして何の賢明なデフォルト値がありません。これらのプロパティは、コンストラクタパラメータを使用して初期化する必要があります。

    • ユーザーがオプションで設定または上書きできるオブジェクトプロパティ。コンストラクタでこのようなプロパティを初期化することもできますが、別のコンストラクタパラメータを持つ必要はありません。その代わりに、セッターメソッドを使用してユーザーがオーバーライドできるように、わかりやすいデフォルト値を割り当てることができます。プロパティ派生クラスで抽象ゲッターをオーバーライドを介して提供される:

      abstract class ComplicatedFoo { 
          protected abstract T getSomeDependency(); // replaces required ctor parameter 
      } 
      

    も特性の第一のタイプ(絶対ユーザ提供の値を有していなければならないもの)に対する代替あり

    PS:書籍"Dependency Injection" by Dhanji R. Prasanna (Manning Publications)は、オブジェクトの初期化方法のさまざまな方法の概要をよく示しています。

  • 2

    どちらもありません。 巨大なパラメータリストはオブジェクトが多すぎることを示します。オブジェクトが有効で有用な出力を得る前に設定する必要のあるプロパティは、あまりにも多くのことを示しています。 だから私の限りでは解決策はありません。

    これらの問題を解決する方法はたくさんありますが、特定のシナリオの外には、「実行する必要があります」という唯一のルールがあります。

    他のオブジェクト、「コントローラ」クラス、さまざまなコミュニケータパターンへの集約。いくつかのカテゴリファーストクラスのオブジェクトは、いくつかの実装で非表示にすることができます。

    あなたが提示した2つのオプションは唯一のものであるとは限りません。ただし、コードをドアの外に出すという意味での実用的な点を除きます。私が選択しなければならなかったものは、コードが必要とするさまざまなパラメータを持つコンストラクタへの呼び出し回数と、すべてのプロパティが設定されていることを確認するために必要な検証と、おそらくユニットテストへの影響に依存します。オブジェクトが混乱していると扱いにくいか制限されているからです。