2

问题

我在 F# 中有表示逻辑树的代码。它是一个具有一些相当简单的数学函数的业务规则引擎。我希望能够多次运行树的规则,并查看通过树的每条特定路线被采用了多少次。

要求是基本规则不应该与我目前使用的简单匹配语句改变太多。用属性标记重要函数会很好,但在每个节点上添加对日志记录函数的调用就不行了。我希望能够以两种模式运行代码,一种是只提供答案的高性能标准模式,另一种是在每次调用背后提供更多细节的“探索模式”。虽然我不介意动态加载和分析规则的复杂代码,但规则代码本身必须看起来很简单。理想情况下,我不想依赖 3rd 方库——powerpack 没问题。该解决方案还必须以 .NET 4.0 运行时为目标。

潜在的解决方案

  1. 使用函数名称和参数向每个函数添加日志记录调用。我不喜欢这样,因为即使我可以在某种发布模式下禁用它,它仍然会使规则混乱,并且意味着所有新代码都必须以不自然的方式编写。

  2. 每个函数返回它的结果,然后是一个列表,其中包含迄今为止调用的方法的名称。我不喜欢这样,因为它看起来不自然,并且会影响性​​能。我确信我可以使用计算表达式来完成很多工作,但这违反了保持规则简单的要求。

  3. 使用引号解析规则树,然后构建一个新表达式,它是旧表达式,并调用注入到每个标记函数的站点中的日志记录函数。这是迄今为止我得到的最好的东西,但我担心编译生成的报价以便我可以运行它。我了解(如果我错了,请纠正我)并非所有引文都可以编译。我宁愿没有将规则代码限制为 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
4

0 回答 0