When writing object-oriented software, I use dependency injection a lot:
-
to compose together high-level functionality from lower-level capabilities: my account management service uses repositories and validation services rather than implementing them itself.
-
to isolate components from their dependencies: my account management service uses its dependencies through interfaces, so that I can swap implementations, mock for unit testing and so on.
What patterns exist in functional programming languages to achieve these goals?
edit: a commenter rightly asks: “what about just passing round functions?”. I think that the following comment about function grouping hits the nail on the head – a service is a collection of functions with a shared set of dependencies that I can handle as an atomic group.
In Clojure it seems like protocols solve this nicely, but I was really wondering how the problem is solved more generally…
At the small scale, things like currying and functions-as-parameters cut down the need for module dependencies. At a larger scale, things like Standard ML functors are very useful for this purpose. Racket has a system called units that does a good job on this too.