問題
論理ツリーを表す F# のコードがあります。これは、かなり単純な数学関数を備えたビジネス ルール エンジンです。ツリーのルールを何度も実行して、ツリーを通る特定の各ルートが何回使用されるかを確認できるようにしたいと考えています。
要件は、現在使用している単純な一致ステートメントから基本ルールをあまり変更しないことです。重要な関数に属性のタグを付けるのは問題ありませんが、すべてのノードでロギング関数の呼び出しを追加するのは適切ではありません。コードを 2 つのモードで実行できるようにしたいと考えています。1 つは応答のみを提供する高パフォーマンスの標準モードで、もう 1 つは各呼び出しの背後にある詳細を提供する「探索モード」です。ルールを動的にロードしてプロファイリングするための複雑なコードは気にしませんが、ルール コード自体は単純に見える必要があります。理想的には、サードパーティのライブラリに依存したくない - powerpack は問題ありません。ソリューションは、.NET 4.0 ランタイムもターゲットにする必要があります。
考えられる解決策
関数名と引数を使用して、すべての関数にログ呼び出しを追加します。ある種のリリース モードで無効にできたとしても、ルールが乱雑になり、すべての新しいコードを不自然な方法で書かなければならないことを意味するため、これは好きではありません。
各関数はその結果を返し、それまでに呼び出されたメソッドの名前を含むリストを返します。不自然に見え、パフォーマンスに影響を与えるので、私はこれが好きではありません. 計算式を使用して多くの配管を行うことができると確信していますが、それはルールを単純に保つという要件に違反しています。
引用符を使用してルール ツリーを解析し、タグ付けされた各関数のサイトに挿入されたログ関数への呼び出しを含む古い式である新しい式を作成します。これは私がこれまでに得た最高のものですが、実行できるように結果の見積もりをコンパイルすることについて心配しています. すべての引用を編集できるわけではないことを理解しています (間違っていたら訂正してください)。ルール コードを F# 言語のサブセットに制限する不安定なプロセスは避けたいと思います。ルールがコンパイルされたら、ソリューションでそれらを処理できるようにしたいと思います。
これはかなり厳しい一連の要件を伴う難しい問題であることは承知していますが、誰かが解決策のインスピレーションを持っている場合は、非常に感謝しています.
編集:私が使用している可能性のあるルールの例を示すために、製品AとBを生産するウィジェット工場を所有している場合、次の単純なコードが使用される可能性があります。このレイヤーをヘルパー関数とフックで装飾することで、数式の読みやすさと単純さを失いたくありません。
type ProductType = | ProductA | ProductB
let costOfA quantity =
100.0 * quantity
let costOfB quantity =
if quantity < 100.0 then
20.0 * quantity
else
15.0 * quantity
let calculateCostOfProduct productType quantity =
match productType with
| ProductA -> costOfA quantity
| ProductB -> costOfB quantity