Hey, I’m used to OOP, but am interested in learning more about FP and in particular using OCaml as a web server.
I am at the very start, but I am already facing some barriers and can’t find good resources on how to solve these very basic and fundamental problems.
I went through the thread about functions as DI and this reply really describes my issue: Functors for dependency injection?
I am used to structuring code through DI like this:
interface Logger {
info: (message: string) => void;
error: (message: string) => void;
}
interface Service {
run: (req: Request) => Response;
}
class MyService implements Service {
constructor(private readonly Logger logger) {
}
run(req: Request): Response {
this.logger.info("starting run");
// ...
return res;
}
}
What this allows me is to have one logger implementation in development (for example logging to the console), but entirely different logger implementation in production (like sending messages to a remote API);
It allows easy testing as well since we can test MyService
by passing fake db/repository implementations, so we don’t need a DB to test our service
Using modules and passing them around is the closest thing that comes to mind, but in the linked article @rgrinberg points out that this comes with its own set of problems and there are better ways.
I have also tried passing functions, for example
const run = (req: Request, info: (message: string) => void, ...): Response {
info("starting run");
// ...
return res;
}
but this only creates new problems - now static dependencies need to be wired through every single function, which is very tedious once the dependencies increase.
I have also tried using a service locator where a singleton object is created that can be “queried” for services, similar to: https://github.com/giraffe-fsharp/samples/blob/57128d2d295c06aac2791d01a22fa2291139927d/demo-apps/IdentityApp/IdentityApp/Program.fs#L126
but this also looks like a step in the wrong direction since now instead of listing dependencies in constructors, they become hidden, making testing;
I am starting to feel like classes are so popular, because they are the right solution for this use case,
or I am missing some very fundamental information about how to solve this with FP concepts.
Can anyone please make a concrete suggestion on how this problem can be solved?