I'm gradually switching into F# for a lot of my home projects but I'm a little stumped as to how to wire together complete applications, and more particularly cross-cutting concerns.
In C# if I want to log stuff I'd use dependency injection to pass an ILogger into each class, and then this can be called nice and easily from the code. I can verify in my tests that given a particular situation logs are written, by passing in a mock and verifying it.
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;
}
}
In F# I'm using modules a lot more, so the above would become
module Stuff
let divde x y =
match y with
| 0 -> 0
| _ -> x / y
Now if I had a module called Logging I could just open that and use a log function from there in the case of y being 0, but how would I inject this for unit testing?
I could have each function take a log function (string -> unit) and then use partial application to wire them up but that seems like an awful lot of work, as would creating a new function that wraps the actual call inside a logging call. Is there a particular pattern or a bit of F# that I'm missing that can do it? (I've seen the kprintf function but I still don't know how you'd specify the function for various test scenarios, whilst using a concrete implementation for the complete application)
Similarly how would you stub out a repository that fetched data? Do you need to have some class instantiated and set the CRUD functions on it, or is there a way to inject which modules you open (aside from #define)