Scala is all about scalable,functional, immutability and most importantly less piece of code!
While building a framework using shared-nothing architecture, i came across the requirement of linking/referencing various modules(rather services) together. Dependency injection was an obvious choice. Let’s take ahead this discussion with further exploration of Dependency Injection(DI) and various possible ways to accomplish it
Dependency Injection
It is basically providing the objects that an object needs (its dependencies) instead of having it construct them itself. It’s a very useful technique for testing, since it allows dependencies to be mocked or stubbed out.In other word, Dependency injection is a design pattern whose core principle is to separate behavior from dependency resolution.
There is an article by Martin Fowler that can provide more insights about DI.
Basically needs of DI are:
Unit testing
Mock Data Access Layer
Mock File System
Mock Email
Modular design
Multiple different implementation
Upgradeable infrastructure
Separation of concern
Single Responsibility
Increase code Re-Use
Cleaner Modeling
Concurrent or independent development
To summarize, Dependency injection is a software design pattern in which any dependency object has should be provided that dependency instead of internally create with in an object.Actually this implementation Dependency Inversion Principle.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.
Let’s talk about developer business, i.e. implementation.
Talking about scala and DI, there are multiple alternatives are available, few popular ones are:
1.Constructor injection
2.Cake pattern
3.Google guice
Constructor injection
As the name says itself!, Declare all required dependencies for an object as constructor arguments. Great! but how does it work?Well, lets take on this with an example
A UserService class that take user information from database and do some operation.
So first we need to get data from database for that , define a class UserDAL which have create ,update, delete methods on database rows.
Now define a UserService class , UserService class have some operation on data those provided by UserDAL class. UserService class have dependency on UserDAL so UserService class declare UserDAL class as a constructor parameter.
Something wrong in design. Any guesses ? Take a closer look
class UserService(userDAL: UserDAL) {
You answer is violation of Dependency Inversion Principle.
The principle states:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
So we define a trait :
UserService depend on UserDALComponent(abstraction) not implemention.
Cake Pattern
The current strategy we are using is based on the so-called Cake Pattern. Cake Pattern is first explained in Martin Oderskys’ paper Scalable Component Abstractions (which is an excellent paper that is highly recommended) as the way he and his team structured the Scala compiler.Lets discuss by Example:
Here class UserDAL are defined inside UserDALComponent trait with abstract reference variable of UserDAL . Question is that why reference variable is abstract. Because if you writing unit test of UserService then you can mock UserDAL easily.(By mocking framework). and second reason is violation of Dependency Inversion Principle.
Google Guice
Google Guice is an open source software framework for the Java platform released by Google under the Apache License.It provides support for dependency injection using annotations to configure Java objects.Dependency injection is a design pattern whose core principle is to separate behavior from dependency resolution.
Basically Google guice framework are made for java but we can use as well in scala.
sbt dependency for Google guice;
Lets discuss by a Example:
Guice requeries a extra configuration class in which we bind trait with thier implementing class.
Guice take all responsibilty of depencencies and object creation.
References:
1. A very popular blog on DI by Jonas boner.
2.Inversion of Control Containers and the Dependency Injection pattern By Martin Fowler.
Happy programming !!! Keep innovating 🙂
For a general overview on how to to DI in Scala using predominantly language constructs, take a look at the “DI in Scala: Guide” (http://di-in-scala.github.io/)