Dependency injection in Scala

Post on 10-May-2015

1.452 views 2 download

Tags:

description

Dependency injection in Scala done without any frameworks.

Transcript of Dependency injection in Scala

Alf Kristian StøyleKnow IT Objectnet

Hvordan vi klarte oss uten Spring,dependency injection i Scala

Dependency Injection

Transactions

Cake pattern‘Cake Pattern’ because “(...) beyond my

appreciation of cake, [a] cake is made of a number of layers (separated by jam), and

can be sliced. The layers represent the different levels of inner class nesting. It is

conceivable that you would reach the bottom layer by working your way down

from the top.

http://scala.sygneca.com/patterns/component-mixins

case class User(username: String, password: String)

class UserRepository { def authenticate(user: User): User = { println("authenticating user: " + user) user } def create(user: User): User = { println("creating user: " + user) user }}

class UserService {

val userRepository = new UserRepository

def authenticate(username: String, password: String): User = userRepository.authenticate(new User(username, password)) def create(username: String, password: String): User = userRepository.create(new User(username, password))}

class UserRepository { def authenticate(user: User): User = { println("authenticating user: " + user) user } def create(user: User): User = { println("creating user: " + user) user }}

trait UserRepositoryComponent {

val userRepository: UserRepository class UserRepository { def authenticate(user: User): User = { println("authenticating user: " + user) user } def create(user: User): User = { println("creating user: " + user) user } } }

class UserService { def authenticate(username: String, password: String): User = userRepository.authenticate(new User(username, password)) def create(username: String, password: String): User = userRepository.create(new User(username, password))}

trait UserServiceComponent {

val userService: UserService

class UserService { def authenticate(username: String, password: String): User = userRepository.authenticate(new User(username, password)) def create(username: String, password: String): User = userRepository.create(new User(username, password)) } }

//val userRepository: UserRepository

extends UserRepositoryComponent

trait UserServiceComponent { self: UserRepositoryComponent =>

val userService: UserService

class UserService { def authenticate(username: String, password: String): User = userRepository.authenticate(new User(username, password)) def create(username: String, password: String): User = self.userRepository.create(new User(username, password)) } }

//val userRepository: UserRepository

object ComponentRegistry extends UserServiceComponent with UserRepositoryComponent { val userRepository = new UserRepository val userService = new UserService }

val userService = ComponentRegistry.userService val user = userService.authenticate("user", "password")// => User(user,password)

import org.mockito.Mockito._

class TestingEnvironment extends UserServiceComponent with UserRepositoryComponent { val userRepository = mock(classOf[UserRepository]) val userService = new UserService }

val testEnv = new TestingEnvironmentwhen(testEnv.userRepository .authenticate(new User("user", "password"))) .thenReturn(new User("mock", "mockpwd"))val userService = testEnv.userServiceval user = userService.authenticate("user", "password")// => User(mock,mockpwd)

Gotchas

• Class vs Object

• Typenavn

Andre måter

• Structural types

• Implicit declarations

• Functional currying

• Spring

• Guice

Transactions

import org.springframework.transaction.annotation.Transactional

class UserService { @Transactional def create(username: String, password: String) = { userRepository.create(new User(username, password)) }}

Transactions

import TransactionManager._

class UserService { def create(username: String, password: String) = transactional { userRepository.create(new User(username, password)) }}

object TransactionManager { def transactional[A](work: => A): A = ...}