Dependency injection is a common pattern in enterprise applications, and several popular frameworks sprang up in the Java universe to solve the problems associated with dependency injection. Indeed, sometimes a key reason for using an enterprise framework, such as Spring or Guice, is motivated by those frameworks' support for dependency injection, allowing loser coupling of an application's components.
Applications written in other languages, however, often don't have to devote as much attention to dependency injection. One reason for that is that some languages provide built-in facilities that can help solve the problems associated with dependency injection without having to resort to an external framework.
Although Scala is a statically typed language, it provides several such features. In a recent blog post, Real-World Scala: Dependency Injection (DI), Jonas Bonér explains various approaches Scala developers can take to dependency injection:
Scala is a very rich and deep language that gives you several ways of doing DI solely based on language constructs, but nothing prevents you from using existing Java DI frameworks, if that is preferred.
The gist of Bonér's post focuses on the "cake pattern," first expatiated on by Scala creator Martin Odersky:
This pattern is first explained in Martin Odersky’s paper Scalable Component Abstractions (which is an excellent paper that is highly recommended) as the way he and his team structured the Scala compiler...
As Alex Boisvert pointed out in a message to the Scala mailing list, "The Cake pattern is a metaphor taken from the cooking world whereby you prepare several cake layers independently and then join them together at the end -- with icing and a little sugar on top!"
Bonér illustrates this concept with a running example that he refactors throughout the article. The technique, in effect, creates several modules and then merges them in a way that allows those modules to develop independently of each other:
In order to do that the only thing we need to do is to merge/join the different namespaces into one single application (or module) namespace. This is done by creating a “module” object composed of all our components. When we do that all wiring is happening automatically...
One of the beauties here is that all wiring is statically typed. For example, if we have a dependency declaration missing, if it is misspelled or something else is screwed up then we get a compilation error. This also makes it very fast...
Another beauty is that everything is immutable (all dependencies are declared as val).
In order to use the application we only need to get the “top-level” component from the registry, and all other dependencies are wired for us (similar to how Guice/Spring works).
In the post, Bonér also explains other possible Scala dependency injection techniques, such as one using structural types, and another one using implicits.
Do you think Scala makes dependency injection easier? What are your favorite Scala techniques for dependency injection?