純粋な関数を書くという考えは好きですが、それらを組み合わせてテスト可能なコードにする方法を理解するのに苦労しています。私はクラスを抽出してから適切にスタブ化することに慣れており、関数型プログラミングに関するいくつかの重要な洞察が欠けていると感じています。
これは、現在直面している問題からスリム化した例です。
日付のリストのリストを取得し、「機会」の基準を満たすものをフィルタリングしたいと考えています。
C# では次のようになります。
static List<List<DateTime>> Opportunities(List<List<DateTime>> dates)
{
return dates.Where(ds => HasOpportunity(ds)).ToList();
}
static bool HasOpportunity(List<DateTime> dates)
{
var threshold = 0.05D;
var current = OpportunityProbability(dates, DateTime.Now);
var previous = OpportunityProbability(dates, DateTime.Now.Subtract(TimeSpan.FromDays(30)));
return previous >= threshold && current < threshold;
}
static double OpportunityProbability(List<DateTime> dates, DateTime endDate)
{
// does lots of math
return 0.0D;
}
したがって、ヒントでは、OpportunityProbability
テスト方法を知っています。私が抱えている問題はHasOpportunity
、チェーン ( ) のさらに上にありOpportunities
ます。
テストする方法を知っている唯一の方法HasOpportunity
は、スタブアウトするOpportunityProbability
ことですが、それはできません。OpportunityProbability
また、 をテストするために、 の設計を満たすために偽のデータを作成したくありませんHasOpportunity
。したがって、両方の関数が純粋であるにもかかわらず、テスト可能ではなく、設計が悪いように感じます。
したがって、私は悪い機能コードを設計しているように感じます:)
私が気にしてHasOpportunity
いるのは、主にブール値のテストです。2 つの double としきい値を指定すると、比較が行われ、結果が返されます。これらの 2 つの double を取得するために、日付のリストと日付を必要とする関数を使用します。これにより、日付 (および 30 日前)HasOpportunity
の決定も担当することになります。DateTime.Now
多分私はそれを分割することができます:
static bool HasOpportunity(double probability1, double probability2)
{
var threshold = 0.05D;
return probability2 >= threshold && probability1 < threshold;
}
したがって、それは明らかにテスト可能です。しきい値を上に移動することもできます。
static bool HasOpportunity(double threshold, double probability1, double probability2)
{
return probability2 >= threshold && probability1 < threshold;
}
したがって、これはさらに一般的です。
これを行うときに遭遇する問題は、次のように移動したことOpportunities
です。
static List<List<DateTime>> Opportunities(List<List<DateTime>> dates)
{
return dates.Where(ds => {
var current = OpportunityProbability(ds, DateTime.Now);
var previous = OpportunityProbability(ds, DateTime.Now.Subtract(TimeSpan.FromDays(30)));
return HasOpportunity(0.05D, current, previous);
}).ToList();
}
これは、次に取るべきステップがわからないところです。
機能的な大君主について何か考えはありますか?C# で F# を書くのを手伝ってください。よろしくお願いします!
アップデート
したがって、別の一歩を踏み出すと、次のようになります。
static List<List<DateTime>> Opportunities(double threshold, DateTime currentDate, DateTime previousDate, List<List<DateTime>> dates)
{
return dates.Where(ds => {
var current = OpportunityProbability(ds, currentDate);
var previous = OpportunityProbability(ds, previousDate);
return HasOpportunity(threshold, current, previous);
}).ToList();
}
したがって、これをテストする方法はまだわかりませんが、この関数のパラメーターが最終的に機会の定義を作成するという点で優れています。
- しきい値
- 初めてのデート
- 二日目
そして、日付のリストのリストがあれば、機会を与えることができます。