Dependency
injec+on
in
Scala
The sequel - SubCut
javaBin, Trondheim – 1.12.2011
Slide 2
Slide 2 text
SubCut
Scala
Uniquely
Bound
Classes
Under
Traits
Slide 3
Slide 3 text
History
lesson
SubCut
(My
personal)
Crystal
Ball
Scala
Uniquely
Bound
Classes
Under
Traits
Slide 4
Slide 4 text
History
lesson
Constructor
injec+on
Cake
pa?ern
new SomeClass(dep1, dep2)
…
Slide 5
Slide 5 text
trait SomeComponent {
val aThing: SomeInterface
trait SomeInterface {
// Stuff
}
}
trait AnotherComponentImpl extends AnotherComponent {
this: SomeComponent =>
def myMethod {
aThing.usefulStuff()
}
}
object ComponentRegistry extends AnotherComponentImpl
with SomeComponentImpl {
val aThing = new MyFavouriteImpl
}
Slide 6
Slide 6 text
Let’s
(Sub)Cut
to
it
Slide 7
Slide 7 text
object ProjectConfiguration extends NewBindingModule({ module =>
import module._ // can now use bind directly
bind [UserRepository] toInstance new RealUserRepository
bind [Analyzer] identifiedBy 'webAnalyzer to
instanceOfClass [WebAnalyzer]
bind [Session] identifiedBy 'currentUser toProvider
{ WebServerSession.getCurrentUser().getSession() }
bind [Int] identifiedBy 'maxThreadPoolSize
toInstance 10
bind [WebSearch] toLazyInstance
{ new GoogleSearchService()(ProjectConfiguration) }
...
})
Configura+on
module
Slide 8
Slide 8 text
Injectable
class
object ProjectConfiguration extends NewBindingModule({ module =>
...
})
class UserService(val serviceId: String,
webAnalyzer: Option[Analyzer] = injected)
(implicit val bindingModule: BindingModule)
extends Injectable {
val userRepository = inject[UserRepository]
val maxPoolSize = injectIfBound[Int]('maxThreadPoolSize) { 15 }
val myAnalyzer = injectIfMissing[Analyzer](webAnalyzer)
...
}
Slide 9
Slide 9 text
Configuring
your
app
implicit val bindingModule = ProjectConfiguration
val topInstance = new UserService("myUserService")
Slide 10
Slide 10 text
Configuring
your
app
implicit val bindingModule = ProjectConfiguration
val topInstance = new UserService("myUserService")
val topInstance = new UserService("myUserService")(ProjectConfiguration)
Slide 11
Slide 11 text
Configuring
your
app
implicit val bindingModule = ProjectConfiguration
val topInstance = new UserService("myUserService")
val topInstance = new UserService("myUserService")(ProjectConfiguration)
trait ProjectBindings {
implicit val bindingModule: BindingModule = ProjectConfiguration
}
class MyApp extends Injectable with ProjectBindings {
// ...
}
Slide 12
Slide 12 text
Configuring
your
app
implicit val bindingModule = ProjectConfiguration
val topInstance = new UserService("myUserService")
val topInstance = new UserService("myUserService")(ProjectConfiguration)
class SomePage(implicit val bindingModule: BindingModule)
extends WicketPage with Injectable { }
class ProdSomePage extends SomePage(ProjectConfiguration)
trait ProjectBindings {
implicit val bindingModule: BindingModule = ProjectConfiguration
}
class MyApp extends Injectable with ProjectBindings {
// ...
}
Slide 13
Slide 13 text
Tes+ng
test(”SubCut scalatest test 1") {
ProjectConfiguration.modifyBindings { module =>
// new calls to bind inside here
val service = new UserService("myUserService")(module)
// all testcode using service also goes inside here
}
}
Slide 14
Slide 14 text
Tes+ng
val testConfig = ProjectConfiguration.modifyBindings { module =>
// new calls to bind inside here
module
}
val service = new UserService(“myOtherService”)(testConfig)
test(”SubCut scalatest test 2") {
// testcode using service goes here
}
test(”SubCut scalatest test 1") {
ProjectConfiguration.modifyBindings { module =>
// new calls to bind inside here
val service = new UserService("myUserService")(module)
// all testcode using service also goes inside here
}
}
Slide 15
Slide 15 text
Tes+ng
val testModule = TestProjectConfiguration :: ProjectConfiguration
val mergedService = new UserService("myMergedService")(testModule)
test(”SubCut scalatest test 3") {
// testcode using mergedService goes here
}
val testConfig = ProjectConfiguration.modifyBindings { module =>
// new calls to bind inside here
module
}
val service = new UserService(“myOtherService”)(testConfig)
test(”SubCut scalatest test 2") {
// testcode using service goes here
}
test(”SubCut scalatest test 1") {
ProjectConfiguration.modifyBindings { module =>
// new calls to bind inside here
val service = new UserService("myUserService")(module)
// all testcode using service also goes inside here
}
}
Slide 16
Slide 16 text
A
good
(Sub)Cut?
Slide 17
Slide 17 text
What
now?
Slide 18
Slide 18 text
Credits
• “Dependency
Injec+on
Op+ons
in
Scala”
–
Dick
Wall
@
JavaZone
X
2011
– h?p://vimeo.com/28792660
• h?ps://github.com/dickwall/subcut
• h?ps://github.com/dickwall/subcut/blob/
master/Ge`ngStarted.md
• h?p://stackoverflow.com/ques+ons/7029268/
use-‐subcut-‐scala-‐di-‐on-‐android
• h?ps://github.com/janwe/javaBin-‐ScalaDI
Slide 19
Slide 19 text
BEKK CONSULTING AS
SKUR 39, VIPPETANGEN. P.O. BOX 134 SENTRUM, 0102 OSLO, NORWAY. WWW.BEKK.NO
Jan
Fredrik
Wedén
Manager,
Trondheim
@jfweden