Constructor injection in Scala | subtype [PDF]

Oct 6, 2011 - Scala allows to perform implicit constructor injection in quite elegant manner. This is should not be noth

2 downloads 19 Views 60KB Size

Recommend Stories


Manualul inginerului constructor pdf
Courage doesn't always roar. Sometimes courage is the quiet voice at the end of the day saying, "I will

PdF Scala Cookbook
And you? When will you begin that long journey into yourself? Rumi

Parallel Programming in Scala
Your big opportunity may be right where you are now. Napoleon Hill

14 Veicolo in Scala
Come let us be friends for once. Let us make life easy on us. Let us be loved ones and lovers. The earth

Scala Sockelleisten Scala Skirts
You often feel tired, not because you've done too much, but because you've done too little of what sparks

Code Cube Constructor
So many books, so little time. Frank Zappa

Cervical Epidural Injection (PDF)
If you feel beautiful, then you are. Even if you don't, you still are. Terri Guillemets

Beaufort Scala
Come let us be friends for once. Let us make life easy on us. Let us be loved ones and lovers. The earth

PDF Dependency Injection in .NET Popular Online
We may have all come on different ships, but we're in the same boat now. M.L.King

scala beaufort del vento
You're not going to master the rest of your life in one day. Just relax. Master the day. Than just keep

Idea Transcript


subtype

Constructor injection in Scala Posted on October 6, 2011

There are many ways to do dependency injection (DI) in Scala. Traditional Java DI frameworks such as Guice, PicoContainer and Spring Framework work just fine with Scala. There are even Scala specific DI libraries, such as subcut and sindi, which offer nicer syntax and additional type safety. For me the best part is that you don’t necessarily need any DI framework in Scala. The language is powerful enough to abstract injection quite nicely. The most famous DI technique in Scala is the Cake Pattern. The Cake Pattern is wonderful but bit heavy and in fact it offers more than just DI. The Cake Pattern article also describes two other common methods: using implicit values and structural typing. What I describe next is a version of implicit injection.

Implicit constructor injection in Scala Scala allows to perform implicit constructor injection in quite elegant manner. This is should not be nothing new, of course, but having a neat summary of this pattern is certainly helpful. The terminology used in examples below is borrowed from Guice (modules, binding and injector). It is also worth pointing out the Implicit Environment Pattern which has some similarities. Without further ado, the recipe:

// Service interfaces (optional) trait PlumbingService trait PorcelainService // Implementations declaring dependencies using implicit keyword class PlumbingServiceImpl extends PlumbingService class PorcelainServiceImpl( implicit plumbingSrv: PlumbingService) extends PorcelainService // Dependency modules declaring bindings trait RoyalModule { lazy implicit val plumbingService = new PlumbingServiceImpl lazy implicit val porcelainService = new PorcelainServiceImpl } // Compose an injector from modules class RoyalInjector extends RoyalModule // Profit new RoyalInjector().porcelainService

Summary: 1. Declare service dependencies using implicit keyword in constructor 2. Create dependency modules using traits 3. In each module use ‘implicit lazy val’ to bind dependencies 4. Compose injector class from modules

On usage Overriding dependencies is easy when needed:

trait RoyalTestModule extends RoyalModule { override lazy implicit val plumbingService = new MockPlumbingService }

Addition safety measures can be added for extra robustness:

class PorcelainServiceImpl( implicit plumbingSrv: PlumbingService) extends PorcelainService { require(plumbingSrv != null) // fail-fast if null } trait RoyalModule { // use protected keyword and specify type explicitly protected lazy implicit val plumbingService: PlumbingService = new PlumbingServiceImpl }

“abstract implicit lazy val” would allow abstract binding but unfortunately this doesn’t compile. Luckily, adding one level of indirection helps:

trait MyModule { implicit lazy val myService = createMyService() def createMyService() // abstract method }

Ambiguity problem when injecting multiple different values with the same type signature can be solved either by assigning ambiguous values manually or by using annotated types:

class Annotated[A, T](val value: T) class MyService(implicit hostname: Annotated[MyService, String]) trait MyModule { lazy implicit val myServiceHost = new Annotated[MyService, String]("localhost") }

Finally, I’d like to mention “factory method” injection which can be useful in certain cases where new instance is preferred to singleton instance. As a side note, this is a good example where Cake Pattern performs better since it allows to use def in very natural way.

trait MyModule { lazy implicit val fooFactory: () => Foo = () => new FooImpl }

However, using explicit type such as FooFactory might be more obvious than () => Foo.

The Good, the Bad and the Ugly The Good: Simple Immutable Compile-time injection and type-checking Clean, only implicit keyword is used to declare a dependencies Easy to override when necessary, say, for testing purposes. No need to poison application code with implicit imports (e.g. import FooServices._) Not a library (zero dependencies) The Bad: Cyclic lazy vals will result in a stack overflow on first access (e.g. A depends on B and B depends on A). Breaks super class contract when overriding dependencies: overriding non-abstract values is some what treacherous since val should be immutable forever. One possible workaround is to use “abstract implicit lazy val” at the price of one extra line. Not a library (would offer usage guidance and likely to prevent some mistakes). The Ugly Slightly verbose code in modules Ambiguous implicits must be assigned either manually or some sort of extra type annotation is needed. Finally, the warmer example using the pattern:

// service interfaces trait OnOffDevice { def on: Unit def off: Unit } trait SensorDevice { def isCoffeePresent: Boolean } // service implementations class Heater extends OnOffDevice { def on = println("heater.on") def off = println("heater.off") } class PotSensor extends SensorDevice { def isCoffeePresent = true } // service declaring two dependencies that it wants injected class Warmer( implicit val sensor: SensorDevice, implicit val onOff: OnOffDevice) { def trigger = { if (sensor.isCoffeePresent) onOff.on else onOff.off } } // module binding dependencies trait ServicesModule { protected implicit lazy val potSensor: SensorDevice = new PotSensor protected implicit lazy val heater: OnOffDevice = new Heater } // compose an injector from modules class AppInjector extends ServicesModule { implicit lazy val warmer = new Warmer } // use injector. the wiring is done automatically using // the implicits new AppInjector().warmer.trigger

To highlight main differences to original warmer example pattern: Dependency binding is done in traits instead of objects. Application code is fully unaware of dependency management where as original had to introduce management logic (import Services._). Injection logic is centralized to injector class in contrary to scattered code fragments (import Services._) in application code. This is it for now. Happy hacking!

Report this ad

Report this ad

Share this:

Twitter

Facebook

Like Be the first to like this.

This entry was posted in scala. Bookmark the permalink.

One Response to Constructor injection in Scala Adam Warski says: October 10, 2011 at 2:51 pm

Nice Although one disadvantage, same as with the cake pattern, is that the configuration is fixed, that is you can dynamically decide which implementation of a dependency you want. Reply

subtype Blog at WordPress.com.

Smile Life

When life gives you a hundred reasons to cry, show life that you have a thousand reasons to smile

Get in touch

© Copyright 2015 - 2024 PDFFOX.COM - All rights reserved.