Сервис Scala, разделенный по среде (локатор сервисов?)

Приложение My Scala поддерживает 2 среды: TEST и PROD. Разница в использовании сервисов. Например, рабочий Emailer на самом деле отправляет электронное письмо, а тестовый Emailer скорее заглушка или макет. Среда настраивается параметром. Как вы реализуете такой сервис, разделяющий среду? Вы предпочитаете какое-то решение с DI, такое как Guice?


person Alexander    schedule 30.05.2014    source источник


Ответы (1)


В дополнение к Guice вы можете продолжать использовать нативную инъекцию зависимостей шаблона пирога Scala, если хотите.

// 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
}

Чтобы написать это самостоятельно, требуется несколько строк, но для этого не требуется отдельная структура внедрения зависимостей со своими собственными подробностями аннотаций. Кроме того, вы не столкнетесь с ошибками внедрения зависимостей во время выполнения — компилятор Scala гарантирует, что это сработает.

person DCKing    schedule 30.05.2014