参照型のプロパティを持つオブジェクトのC#でビルダーを作成するにはどうすればよいですか?
-
05-07-2019 - |
質問
作成中の単体テストのテストデータを簡単に作成できるように、ビルダーの構築を開始しました。
ビルダーの基本構造は次のとおりです。
public class MyClassBuilder
{
public int id = 0; //setting the default value here
//allows MyClass to be built with a specific id
public MyClassBuilder WithId(int id)
{
this.id = id;
return this;
}
public MyClass Build()
{
return new MyClass(id);
}
}
このパターンの使用法は次のようになります。
MyClass mc = new MyClassBuilder().WithId(5).Build();
私はそれに満足しています...しかし、質問があるのは、 MyClass
のプロパティが自明ではない場合です....構築方法については少し不確かですデフォルト値を使用します。
public class MyClassBuilder
{
public int id = 0; //setting the default value here
//do I construct the default value using a MySecondClassBuilder?
public MySecondClass mySecondClass;
//allows MyClass to be built with a specific id
public MyClassBuilder WithId(int id)
{
this.id = id;
return this;
}
public MyClassBuilder WithMySecondClass(MySecondClass mySecondClass)
{
this.mySecondClass = mySecondClass;
}
public MyClass Build()
{
return new MyClass(id);
}
}
私の想定では、 MySecondClass
のビルダーを作成し、それを使用してデフォルトの実装を作成します。
私の仮定が正しく、ベストプラクティスであることを誰もが確認できますか?
現在、仮定をテストする過程にありますが、値型ではなくgoogleを使用して構築されたプロパティのみを見つけることができるビルダーパターンの唯一の例なので、この考えをStackOverflowで文書化すると思いました参照タイプ。
解決
ほとんどのものと同様-それは依存します。
mySecondClassフィールドに参照セマンティクスが必要な場合(つまり、別のクラスへの参照を保存する場合)、整数とまったく同じです。デフォルトをnullにすることは完全に許容できます。
ただし、常に値を保証する場合は、2番目のクラスの新しいオブジェクトを構築するか、単に構築する必要があります。
また、参照コピーではなくクローンを作成する場合は、新しいオブジェクトを作成して参照に割り当てる必要があります。
とはいえ、多くの場合、従来のコンストラクターは、流buildなビルドスタイルのインターフェースを試みるよりも適切です。 「混乱」させるのは本当に簡単です。これは、従来のコンストラクターよりもユーザーに依存しているためです。
例として、コードでは、ユーザーがBuildを呼び出さないとどうなりますか?それはまだ何かを返しています(各メソッドがオブジェクトを返すため)が、それは有効ですか?私はあなたのクラスの消費者としては確信がありません。一方、オーバーロードを使用する従来のコンストラクターは、有効なものと無効なものを正確に示し、コンパイル時に強制されます。
他のヒント
単体テストでダミーを使用する複雑なオブジェクトを作成したら、通常、モック/偽装/分離フレームワークに移ります。 C#では、私の好みはMoqですが、Rhino Mocks、Typemockなどのように、いくつかあります。
ここでの利点は、通常、元の型に存在するすべてのプロパティをデフォルト値と空のオブジェクトでスタブ化する機能を備えていることです。偽のオブジェクトを作成するために1行のステートメント以外の操作を行う必要はありません。同時に、テストに関係するプロパティの値に必要な値を返すようにオブジェクトを簡単に構成できます。また、そのようなフレームワークのほとんどは再帰的に偽造をサポートしているため、型内の複雑なオブジェクトも偽造されます。
別のフレームワークを使用したくない理由があります。その場合、Reed Copseyの提案はそれを行う手動の方法になると思います。
モックフレームワークの追加を避ける理由がない場合(これは、テストを分割したと仮定した場合、テストプロジェクトへの依存関係になります)、複雑な型には心からお勧めします。