我正在很多家庭项目中逐渐使用F#,但是对于如何将完整的应用程序结合在一起,尤其是跨领域的问题,我有些困惑。
在C#中,如果我想记录内容,我将使用依赖注入将ILogger传递到每个类中,然后可以从代码中轻松地调用它。通过传递模拟并进行验证,我可以在测试中验证是否已编写了特定情况的日志。
public class MyClass
{
readonly ILogger _logger;
public MyClass(ILogger logger)
{
_logger = logger;
}
public int Divide(int x, int y)
{
if(y == 0)
{
_logger.Warn("y was 0");
return 0;
}
return x / y;
}
}
在F#中,我使用了很多模块,因此上面的内容将成为
module Stuff
let divde x y =
match y with
| 0 -> 0
| _ -> x / y
现在,如果我有一个名为Logging的模块,我可以打开它,并在y为0的情况下从那里使用log函数,但是我该如何将其注入到单元测试中?
我可以让每个函数使用一个日志函数(字符串->单元),然后使用部分应用程序将它们连接起来,但这似乎需要做很多工作,就像创建一个将实际调用包装在日志中的新函数一样呼叫。是否有某种我缺少的特定模式或F#可以做到?(我看过kprintf函数,但是我仍然不知道如何在为整个应用程序使用具体实现的同时为各种测试场景指定该函数)
类似地,您将如何存出提取数据的存储库?您是否需要实例化某个类并在其上设置CRUD函数,或者是否有办法注入您打开的模块(除了#define之外)
我正在很多家庭项目中逐渐使用F#,但是对于如何将完整的应用程序连接在一起,尤其是跨领域的问题,我有些困惑。在C#中,如果需要...
这是基本答案。首先,您似乎认为类和模块是可互换的。类封装了数据,从这个意义上讲,它更类似于记录和DU。另一方面,模块封装功能(它们被编译为静态类)。所以,我想您已经提到了您的选择:部分函数应用程序,将函数作为数据传递或...依赖项注入。对于您的特殊情况,似乎最容易保留自己的东西。
如果您不需要在运行时更改记录器,那么使用编译器指令或#if
在记录器的两个实现之间进行选择(如Daniel所建议的那样)可能是最好和最简单的方法。
这是您在F#中的C#代码的实现,与初始C#相似