DI in scala

DI(Dependency injection)Its a popular concept for decoupling client and server implementations. DI encourages you to use the constructor patterns which means passing the target dependency as a param when the creation source object happens.

Sandeep Jindal
2 min readApr 21, 2020

DI in scala can be achieved by these frameworks:

Comparison chart

Comparison among different options availaible
Photo by Chris Ried on Unsplash

Reader Monad:

Plain construction injection:

val permRepo = new PermissionRepoImpl
val repo = Repo(userRepo, permRepo)
val createUserResp = UserHandlerWithConstructor.createUser(repo, User(1001, "lambda", "admin"))

Injection using monad: A type parameter, a constructor that takes an element of that type, and a flatMap method

val permRepo = new PermissionRepoImpl
val repo = Repo(userRepo, permRepo)
val createUserResp = UserHandlerWithMonad.createUser(User(1001, "lambda", "admin")).run(repo)
Signature of function: def createUser(user: User): Reader[Repo, Long]

Macwire

Testing with Macwire

// main code
package shunting {
trait ShuntingModule {
lazy val pointSwitcher = wire[PointSwitcher]
lazy val trainCarCoupler = wire[TrainCarCoupler]
lazy val trainShunter = wire[TrainShunter]
}
}
// test
class ShuntingModuleItTest extends FlatSpec {
it should "work" in {
// given
val mockPointSwitcher = mock[PointSwitcher]
// when
val moduleToTest = new ShuntingModule {
// the mock implementation will be used to wire the graph
override lazy val pointSwitcher = mockPointSwitcher
}
moduleToTest.trainShunter.shunt()
// then
verify(mockPointSwitcher).switch(...)
}
}

Summary

Compile-time dependency injection:

libraries: Macwire etc.

  • pros: Can validate the presence of dependencies at compile time.
  • cons: Less flexible (e.g., No dynamic type binding)
  • cons: Need to enumerate all dependencies in the same scope (lengthy code).
  • cons: Hard to implement life cycle management (e.g., onStart, onShutdown, etc.).

Run-time dependency injection

libraries: Google Guice, etc.

  • pros: Allows dynamic type binding.
  • pros: Simpler binding codes. Only need to bind direct dependencies.
  • pros: inject event handler (Guice).
  • cons: Missed binding founds as a runtime error.

References:

scaldi comparison score sheet Providers https://gist.github.com/gvolpe/1454db0ed9476ed0189dcc016fd758aa https://groups.google.com/forum/#!topic/scaldi/TYU36h7kGqk

P.S: Oleg Ilyenko has passed away so not sure about the maintenance of scaldi. Not to mention he was creator of sangria too :sad:

--

--