これは正しい使い方を試験クラスを利用した工場のパターン?
-
19-09-2019 - |
質問
持っていない多くの経験、工場パターンからシナリオの場であると考えている必要がなんなのか、私のパターンを正確にい影響を与えるのかっているわけではないので、読みやすさの単位。
私がコードスニペットに近似した(メモリ)の本質をシナリオに取り組んでます。いい感謝の思いであっし込み頂きありがとうございませんどろ風mikiモデルを作ってみを行います。
このクラスのための試験
public class SomeCalculator : ICalculateSomething
{
private readonly IReducerFactory reducerFactory;
private IReducer reducer;
public SomeCalculator(IReducerFactory reducerFactory)
{
this.reducerFactory = reducerFactory;
}
public SomeCalculator() : this(new ReducerFactory()){}
public decimal Calculate(SomeObject so)
{
reducer = reducerFactory.Create(so.CalculationMethod);
decimal calculatedAmount = so.Amount * so.Amount;
return reducer.Reduce(so, calculatedAmount);
}
}
ちのいくつかを紹介しましょう基本的なインタフェース定義を...
public interface ICalculateSomething
{
decimal Calculate(SomeObject so);
}
public interface IReducerFactory
{
IReducer Create(CalculationMethod cm);
}
public interface IReducer
{
decimal Reduce(SomeObject so, decimal amount);
}
この工場は私を作成します。私の現在の要求という追加の特定の減速機MethodAReducer使用する特定のシナリオるようにしていをご紹介します。
public class ReducerFactory : IReducerFactory
{
public IReducer Create(CalculationMethod cm)
{
switch(cm.Method)
{
case CalculationMethod.MethodA:
return new MethodAReducer();
break;
default:
return DefaultMethodReducer();
break;
}
}
}
これらは近似の実装を...の本質を実施することのみを削減した場合、オブジェクトが特定の状態です。
public class MethodAReducer : IReducer
{
public decimal Reduce(SomeObject so, decimal amount)
{
if(so.isReductionApplicable())
{
return so.Amount-5;
}
return amount;
}
}
public class DefaultMethodReducer : IReducer
{
public decimal Reduce(SomeObject so, decimal amount)
{
if(so.isReductionApplicable())
{
return so.Amount--;
}
return amount;
}
}
この試験治具を使用しています。何の関係というのはどのくらい空間での試験、工場パターンでの取り扱い方を示すことにより削減の可読性ます。ご注意ください私の実世界クラスのいいくつかの依存関係を必要とすることを模擬るこの試験は複数のラインよりも短いものを必要なも実世界のテストです。
[TestFixture]
public class SomeCalculatorTests
{
private Mock<IReducerFactory> reducerFactory;
private SomeCalculator someCalculator;
[Setup]
public void Setup()
{
reducerFactory = new Mock<IReducerFactory>();
someCalculator = new SomeCalculator(reducerFactory.Object);
}
[Teardown]
public void Teardown(){}
最初の試験
//verify that we can calculate an amount
[Test]
public void Calculate_CalculateTheAmount_ReturnsTheAmount()
{
decimal amount = 10;
decimal expectedAmount = 100;
SomeObject so = new SomeObjectBuilder()
.WithCalculationMethod(new CalculationMethodBuilder())
.WithAmount(amount);
Mock<IReducer> reducer = new Mock<IReducer>();
reducer
.Setup(p => p.Reduce(so, expectedAmount))
.Returns(expectedAmount);
reducerFactory
.Setup(p => p.Create(It.IsAny<CalculationMethod>))
.Returns(reducer);
decimal actualAmount = someCalculator.Calculate(so);
Assert.That(actualAmount, Is.EqualTo(expectedAmount));
}
二次試験
//Verify that we make the call to reduce the calculated amount
[Test]
public void Calculate_CalculateTheAmount_ReducesTheAmount()
{
decimal amount = 10;
decimal expectedAmount = 100;
SomeObject so = new SomeObjectBuilder()
.WithCalculationMethod(new CalculationMethodBuilder())
.WithAmount(amount);
Mock<IReducer> reducer = new Mock<IReducer>();
reducer
.Setup(p => p.Reduce(so, expectedAmount))
.Returns(expectedAmount);
reducerFactory
.Setup(p => p.Create(It.IsAny<CalculationMethod>))
.Returns(reducer);
decimal actualAmount = someCalculator.Calculate(so);
reducer.Verify(p => p.Reduce(so, expectedAmount), Times.Once());
}
}
ではの見える。では、よりよい使い方を工場のパターン?
解決
この長い質問だいのだが、ここでも迷うな思想を貫いています。
- AFAIKありません"工場"パターンです。あるパターンと呼ばれ 工場概要 とうという ファクトリメソッド.今まで見えます使用する抽象工場とする。
- 理由はありませんがSomeCalculatorい
reducerFactory
やreducer
ます。くの一つとして、現在の実装する必要がなくなり、より快適なのreducer
ます。 - の注入依存性
reducerFactory
)読み取り専用になります。 - くデフォルトのコンストラクタです。
- スイッチを書ReducerFactoryするコードの香りがする。あとだれかの作成方法にCalculationMethodクラスです。ることが本質的には変更の概要工場の工法です。
いずれの場合がありずにまつわるオーバーヘッドを紹介しながらゆったりカップリングがないと思うのでそこにtestabilityだけます。 Testabilityは本当にのみ開/閉原則, では全てのユーザー様にご利用コードより柔軟で多くの方だきます。
ありがあり、価格支払う、それだけの価値がある。
ほとんどの場合、注入依存関係の読み取り専用になります。な技術的に必要としていますが、エレベルの安全性の分野をリードC# readonly
キーワードとなります。
することを決定したときにあなたに利用DIは、利用でを一貫して行います。この過負荷のコンストラクタが、他の抗パターンです。このコンストラクタ曖昧であることにもつながる 締結 や 漏れに抽象化.
このカスケードがありのように聞こえるかもしれない欠点がある。時を作成する必要がありますの新しいインスタンスSomeCalculatorその他のクラスは、必ず再度のいずれかを注入では入また抽象的な工場で作るようにしています。のがき抽出しインターフェースからSomeCalculatorなISomeCalculator)を注入することです。おめでとうございますの効果的分離のクライアントSomeCalculatorからIReducerとIReducerFactory.
必要なDIコンテナなこと-できるワイヤーまでを手動でインスタンスです。これを 純ージ.
での移動の論理ReducerFactoryにCalculationMethod、仮想方法です。のようなこと:
public virtual IReducer CreateReducer()
{
return new DefaultMethodReducer();
}
特CalculationMethods、それをオーバーライドCreateReducer方法を返し異なる減速機:
public override IReducer CreateReducer()
{
return new MethodAReducer();
}
この最後の助言の意味をなにより多くの情報がないので、そのすべ 検討 いい意味でお客様の特定の。