Reputation: 387
My Scala application supports 2 environments: TEST and PROD. The difference is in using services. For example, production Emailer actualy sends an email, and test Emailer is rather stub or mock. The environment is configured by parameter. How do you implement such a service separating by environment? Do you prefer some solution with DI like Guice?
Upvotes: 1
Views: 339
Reputation: 4283
In addition to Guice, you can keep using the native Scala cake pattern dependency injection if you want.
// MyService.scala
trait MyService {
this: Emailer => // Cake pattern: this must be instatiated with an Emailer trait
def doSomething() {
//...
this.email(...)
//...
}
}
// Somewhere else
trait Emailer { def email(args: String): Unit }
trait MockEmailer { override def email(args: String) = println("Email was sent!") }
trait RealEmailer { override def email(args: String) = actuallySendAnEmail(args) }
// Application.scala
sealed trait Environment
case object Test extends Environment
case object Prod extends Environment
object Application {
private var _environment: Environment = Test // Choose default
def environment = _environment
def main(args: Array[String) {
// Determine environment at startup
if(args.contains("PROD") {
_environment = Prod
} else {
_environment = Test
}
// ...
}
}
// Configuration.scala
val myService = Application.environment match {
case Test => new MyService with MockEmailer
case Prod => new MyService with RealEmailer
}
It takes a handful of lines to write this yourself, but it doesn't require any seperate dependency injection framework with its own annotation verbosities. In addition, you won't encounter runtime dependency injection errors - the Scala compiler guarantees this will work.
Upvotes: 2