SlideShare ist ein Scribd-Unternehmen logo
1 von 30
Downloaden Sie, um offline zu lesen
ScalDI:
Lightweight DI in Scala
umatrangolo@gilt.com
Inversion Of Control
● The Hollywood Principle
"Don't call us, we'll call you"
● You relinquish control on when your code
gets executed to an external framework
○ Windowing system
○ Callbacks
○ High-Order functions
Inversion Of Control
def service(s: String): Future[String] = future {
s.toUpperCase
}
val foo = service(“foo”)
val FOO = Await.result(foo, Duration.Inf)
println(FOO + “ - bar”)
service(“foo”).onSuccess {
case res => println(res + “ - bar”)
}
Not IoC: full control of program flow
IoC: scala.concurrent._ will run your code
Dependency Injection
● A form of IoC where you relinquish the
object creation/initialisation logic
class Manager {
val serviceOne = new ServiceOneImpl()
val serviceTwo = new ServiceTwoImpl()
def tx() {
val id = serviceOne.fetch()
serviceTwo.store(id)
// ...
}
}
object ManagerFactory {
val Instance = new Manager(
new ServiceOneImpl(),
new ServiceTwoImpl()
)
}
class Manager(
private val serviceOne: ServiceOne,
private val serviceTwo: ServiceTwo
) {
def tx() { … }
}
Dependency Injection
● Writing Factories is boring
● IoC containers
○ Spring Framework
○ Google Guice
○ Google Dagger
○ “The Cake Pattern”
○ ScalDI
The Cake Pattern
● Advertised as the Scala way to do DI natively without
any external framework
● Based on the concept of “self-type”
○ Constraints an impl of a type to be also an impl of the defined self
types
trait Foo {
self: Bar with Baz =>
// the Foo type is going to assume that it is also a Bar and a Baz
// ...
}
The Cake Pattern
trait Shell {}
trait Engine {}
trait Car {
self: Shell with Engine =>
}
trait RenaultShell extends Shell {}
trait NissanEngine extends Engine {}
trait NissanShell extends Shell {}
class RenaultScenic extends Car with RenaultShell with NissanEngine {}
class NissanQashqai extends Car with NissanShell with NissanEngine {}
The Cake Pattern
● First introduced by Odersky as the main
modularization tool for the scalac/scala
toolset [1]
● Further evangelized by Boner on his blog [2]
● Easy cookbook on the Cake Solution blog [3]
The Cake Pattern
Let’s use it to build a simple app with this
structure:
UserService
UserDao
MongoDB PostGres
The Cake Pattern
Like:
● No need of a IoC framework
● All your deps are checked at compile time
Don’t like:
● Lots of boilerplate code
● On complex layouts is hard to see what the deps of a module
are
● Introduces ‘hard’ concepts of the Scala type system
● Hard to get it right
● All these traits will slow down compilation time
The Cake Pattern
Truth is that people will start to give up on it
pretty soon shortcutting to abominations like:
trait MyServiceImpl extends MyService
with DependencyA
with DependencyB
with DependencyC
with DependencyD
with DependencyE
with DependencyF
with DependencyG
...
The Cake Pattern
Current Production code in GILT:
object Application extends Journal
with Autocomplete
with ProductLookSearch
with SaleSearch
with CategorySearch
with AgeAndGenderSearch
with HealthCheck
with RuntimeEnvironment
with Prefetch
The Cake Pattern
trait RuntimeEnvironment extends Environment
override val search = ???
override val searchEventPublisher = ???
override val users = ???
override val sales = ???
override val ruleSets = ???
override val productLooksCache = ???
override val productDetailsCache = ???
override val externalProductsCache = ???
override val taxonomiesCache = ???
override val skuJournalsCache = ???
override val publicBrandsCache = ???
override val ruleSetsCache = ???
override val salesCache = ???
override val brandPromotions = ???
override val personalizer = ???
override val kafkaUtil = ???
override val benefitsCache = ???
override val hopperSales = ???
override val redirectClient = ???
override val preferences: Preferences = ???
// … more !!
Who is depending on what ?
The Cake Pattern
trait SaleSearch extends SearchController
with ResponseHelper
with RedirectHelper
with PilHelper
with HopperHelper
with SaleHelper
with ExternalProductViewHelper
with PageComponentsHelper
with TopOfFunnelHelper
with AbTestHelper {
self: Environment =>
// WTF!
// Stuff popping out from nowhere
}
● On what SaleSearch really depends on?
● We basically flattened the dependency graph!!
The Cake Pattern
● Hard to get it right even for Odersky & Co.
● Just happened on scala-internals ML:
https://groups.google.com/forum/#!search/scala-internals$20EECOLOR/scala-internals/Z0kV6iDam0c/-09cDMEz754J
“I do have some opinions about the trait you linked. I think it's design is flawed. Take for example it's base definition:
trait Typechecker extends SymbolTable
with Printers
with Positions
with CompilationUnits
with QuasiquotesImpl
When I read such a type my mind goes something like this:
So Typechecker is a SymbolTable with Printers and Positions and CompilationUnits and QuasiquotesImpl. That instantly sends me to a
place that I don't like….”
“Here we have a peculiar consequence of using the cake pattern. Scalac's codebase illustrates this on a number of occasions as
well.”
The Cake Pattern
// in Implicits.scala
trait Implicits {
self: Analyzer =>
// in Analyzer.scala
trait Analyzer extends AnyRef
with Contexts
with Namers
with Typers
with Infer
with Implicits
with EtaExpansion
with SyntheticMethods
with Unapplies
with Macros
with NamesDefaults
with TypeDiagnostics
with ContextErrors
with StdAttachments
with AnalyzerPlugins
The Cake Pattern
● No control over initialization logic
○ Is not part of the DI definition but is a nice to have
○ With Cake you need to code it yourself
○ Could be problematic due to trait linearization
● Let’s see how it could happen ...
ScalDI
● IMHO the Cake pattern is
○ too much hassle
○ hard to get it right
○ badly implemented could cripple your code base
● Alternatives?
● Be disciplined and write your factory objects
● ScalDI
○ Small and simple
○ Easier to use and to understand
ScalDI
Simple: only 3 concepts
● Injector
○ A container for your bindings
● Module
○ A place where you define the bindings using a nice
DSL
○ It is an Injector
● Injectable
○ Provides a DSL to inject dependencies
ScalDI
Simple example
class DefaultServiceImpl(implicit inj: Injector) extends Service
with Injectable {
val conf = inject [String] (identified by “service.configuration”)
def run() = { println(s”conf: $conf”) }
}
class ServiceModule extends Module {
binding indentifiedBy “service.configuration” to “jdbc://mysql/mydb”
bind [Service] to new DefaultServiceImpl
// bind [Service] toNonLazy DefaultServiceImpl
}
class MyApp(implicit inj: Injector) extends Injectable {
private val service: Service = inject [Service]
}
ScalDI
Module composition
val storeModule = new Module {
bind [UserDao] to new PsqlUserDaoImpl()
bind [OrderDao] to new MongoDbOrderDaoImpl()
}
val cacheModule = new Module {
bind [UserCache] to new LRUUserCacheImpl()
bind [OrderCache] to new TTLOrderCacheImpl()
}
val appModule = storeModule :: cacheModule
// then in test ...
val mocks = new Module {
bind [OrderDao] to new MockOrderDaoImpl()
}
val appModule = mocks :: appModule // will redefine OrderDao with a mock
ScalDI
Constructor injection
class ServiceImpl(dao: Dao, cache: Cache) extends Service { // … }
val module = new Module {
bind [Service] to injected [ServiceImpl]
}
// after macro expansion
val module = new Module {
bind [Service] to new ServiceImpl(
dao = inject[Dao],
cache = inject[Cache]
)
}
ScalDI
You can inject everything!
val myModule = new Module {
binding identifiedBy “greetings” to “Hello World!”
binding identifiedBy “adder” to ((a: Int, b: Int) => a + b)
}
class Consumer(implicit inj: Injector) extends Injectable {
val greet: String = inject [String] (identifiedBy “greetings”)
val adder = inject [(Int, Int) => Int] (identifiedBy “adder”)
}
ScalDI
Conditional injection
val daoModule = new Module {
bind [Dao] when (inDevMode or inTestMode) to new H2Dao()
bind [Dao] when to new PsqlDao()
def inDevMode = !inTestMode && !inProdMode
def inTestMode = System.getProperty(...)
def inProdMode = System.getProperty(...)
}
ScalDI
Lifecycle!
trait Cache {
def start()
def stop()
}
class CacheImpl extends Cache {
def start() = { fetchAll() }
def stop() = { … }
}
val app = new Module { // will init all your bindings
bind [Cache] to new CacheImpl()
initWith { _.start() },
destroyWith { _.stop() }
}
app.destroy() // will invoke all your destroy logics
ScalDI + Play
Can inject into Play controllers!
// with ScalDI a Controller is not an Object!!
// just remember to add a @ in the routes file
class MyController(implicit inj: Injector) extends Controller with Injectable {
private val serviceOne = inject [ServiceOne]
private val serviceTwo = inject [ServiceTwo]
def index = Action {
Ok(serviceOne.run(serviceTwo.run()))
}
}
ScalDI + Akka
Inject Props and ActorRef
class ParentActor(implicit inj: Injector) extends Actor with AkkaInjectable {
val childActorProps = injectActorProps [ChildActor]
val friendActorRef = injectActorRef [FriendActor]
def receive = {
case Spawn => context.actorOf(childActorProps)
case Greet => friendActorRef ! Hello
}
}
ScalDI + Play = DEMO!
ScalDI
I like:
● Easy
● Nice DSL to inject/define dependencies
● Different forms of injections
● Handles lifecycle
● Supports Play and Akka
Don’t like:
● Still somewhat intrusive
EOF

Weitere ähnliche Inhalte

Was ist angesagt?

基于Aws的dev ops实践指南 王毅
基于Aws的dev ops实践指南 王毅基于Aws的dev ops实践指南 王毅
基于Aws的dev ops实践指南 王毅
Mason Mei
 

Was ist angesagt? (20)

apidays LIVE Hong Kong 2021 - GraphQL : Beyond APIs, graph your enterprise by...
apidays LIVE Hong Kong 2021 - GraphQL : Beyond APIs, graph your enterprise by...apidays LIVE Hong Kong 2021 - GraphQL : Beyond APIs, graph your enterprise by...
apidays LIVE Hong Kong 2021 - GraphQL : Beyond APIs, graph your enterprise by...
 
Developing applications with a microservice architecture (svcc)
Developing applications with a microservice architecture (svcc)Developing applications with a microservice architecture (svcc)
Developing applications with a microservice architecture (svcc)
 
AWS Container services
AWS Container servicesAWS Container services
AWS Container services
 
When Our Serverless Team Chooses Containers
When Our Serverless Team Chooses ContainersWhen Our Serverless Team Chooses Containers
When Our Serverless Team Chooses Containers
 
Behavior-Driven Development with JGiven
Behavior-Driven Development with JGivenBehavior-Driven Development with JGiven
Behavior-Driven Development with JGiven
 
基于Aws的dev ops实践指南 王毅
基于Aws的dev ops实践指南 王毅基于Aws的dev ops实践指南 王毅
基于Aws的dev ops实践指南 王毅
 
Haufe Onboarding - Fast Iterating With the MERN Stack - TEC Day 2019
Haufe Onboarding - Fast Iterating With the MERN Stack - TEC Day 2019Haufe Onboarding - Fast Iterating With the MERN Stack - TEC Day 2019
Haufe Onboarding - Fast Iterating With the MERN Stack - TEC Day 2019
 
OSGi DevCon 2009 Review
OSGi DevCon 2009 ReviewOSGi DevCon 2009 Review
OSGi DevCon 2009 Review
 
Nils Rhode - Does it always have to be k8s - TeC Day 2019
Nils Rhode - Does it always have to be k8s - TeC Day 2019Nils Rhode - Does it always have to be k8s - TeC Day 2019
Nils Rhode - Does it always have to be k8s - TeC Day 2019
 
Alon Fliess: APM – What Is It, and Why Do I Need It? - Architecture Next 20
Alon Fliess: APM – What Is It, and Why Do I Need It? - Architecture Next 20Alon Fliess: APM – What Is It, and Why Do I Need It? - Architecture Next 20
Alon Fliess: APM – What Is It, and Why Do I Need It? - Architecture Next 20
 
Benchmarking Service Meshes - CNCF Networking WG
Benchmarking Service Meshes  - CNCF Networking WGBenchmarking Service Meshes  - CNCF Networking WG
Benchmarking Service Meshes - CNCF Networking WG
 
OSGi toolchain from the ground up - Matteo Rulli
OSGi toolchain from the ground up - Matteo RulliOSGi toolchain from the ground up - Matteo Rulli
OSGi toolchain from the ground up - Matteo Rulli
 
WebSockets and Equinox OSGi in a Servlet Container
WebSockets and Equinox OSGi in a Servlet ContainerWebSockets and Equinox OSGi in a Servlet Container
WebSockets and Equinox OSGi in a Servlet Container
 
Magic of web components
Magic of web componentsMagic of web components
Magic of web components
 
Serverless in production (O'Reilly Software Architecture)
Serverless in production (O'Reilly Software Architecture)Serverless in production (O'Reilly Software Architecture)
Serverless in production (O'Reilly Software Architecture)
 
Microservice 4.0 Journey - From Spring NetFlix OSS to Istio Service Mesh and ...
Microservice 4.0 Journey - From Spring NetFlix OSS to Istio Service Mesh and ...Microservice 4.0 Journey - From Spring NetFlix OSS to Istio Service Mesh and ...
Microservice 4.0 Journey - From Spring NetFlix OSS to Istio Service Mesh and ...
 
Itb 2021 - Bulding Quick APIs by Gavin Pickin
Itb 2021 - Bulding Quick APIs by Gavin PickinItb 2021 - Bulding Quick APIs by Gavin Pickin
Itb 2021 - Bulding Quick APIs by Gavin Pickin
 
Radical Agility with Autonomous Teams and Microservices in the Cloud
Radical Agility with Autonomous Teams and Microservices in the CloudRadical Agility with Autonomous Teams and Microservices in the Cloud
Radical Agility with Autonomous Teams and Microservices in the Cloud
 
Usage of Reliable Actors in Azure Service Fabric
Usage of Reliable Actors in Azure Service FabricUsage of Reliable Actors in Azure Service Fabric
Usage of Reliable Actors in Azure Service Fabric
 
A Hitchhiker's Guide to Cloud-Native API Gateways
A Hitchhiker's Guide to Cloud-Native API GatewaysA Hitchhiker's Guide to Cloud-Native API Gateways
A Hitchhiker's Guide to Cloud-Native API Gateways
 

Ähnlich wie Dsug 05 02-15 - ScalDI - lightweight DI in Scala

Java onguice20070426
Java onguice20070426Java onguice20070426
Java onguice20070426
Ratul Ray
 
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas EmbletongDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
George Nguyen
 

Ähnlich wie Dsug 05 02-15 - ScalDI - lightweight DI in Scala (20)

OpenDaylight Developer Experience 2.0
 OpenDaylight Developer Experience 2.0 OpenDaylight Developer Experience 2.0
OpenDaylight Developer Experience 2.0
 
Intro to AngularJs
Intro to AngularJsIntro to AngularJs
Intro to AngularJs
 
Making Steaks from Sacred Cows
Making Steaks from Sacred CowsMaking Steaks from Sacred Cows
Making Steaks from Sacred Cows
 
Web technologies-course 12.pptx
Web technologies-course 12.pptxWeb technologies-course 12.pptx
Web technologies-course 12.pptx
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
Dependency injectionpreso
Dependency injectionpresoDependency injectionpreso
Dependency injectionpreso
 
Awesome html with ujs, jQuery and coffeescript
Awesome html with ujs, jQuery and coffeescriptAwesome html with ujs, jQuery and coffeescript
Awesome html with ujs, jQuery and coffeescript
 
Getting start Java EE Action-Based MVC with Thymeleaf
Getting start Java EE Action-Based MVC with ThymeleafGetting start Java EE Action-Based MVC with Thymeleaf
Getting start Java EE Action-Based MVC with Thymeleaf
 
Robots in Swift
Robots in SwiftRobots in Swift
Robots in Swift
 
Neoito — Design patterns and depenedency injection
Neoito — Design patterns and depenedency injectionNeoito — Design patterns and depenedency injection
Neoito — Design patterns and depenedency injection
 
Need 4 Speed FI
Need 4 Speed FINeed 4 Speed FI
Need 4 Speed FI
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
 
Thinking In Swift
Thinking In SwiftThinking In Swift
Thinking In Swift
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google Guice
 
The MEAN stack
The MEAN stack The MEAN stack
The MEAN stack
 
Angular 2 for Java Developers
Angular 2 for Java DevelopersAngular 2 for Java Developers
Angular 2 for Java Developers
 
Java onguice20070426
Java onguice20070426Java onguice20070426
Java onguice20070426
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas EmbletongDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
 

Kürzlich hochgeladen

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 

Kürzlich hochgeladen (20)

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 

Dsug 05 02-15 - ScalDI - lightweight DI in Scala

  • 1. ScalDI: Lightweight DI in Scala umatrangolo@gilt.com
  • 2. Inversion Of Control ● The Hollywood Principle "Don't call us, we'll call you" ● You relinquish control on when your code gets executed to an external framework ○ Windowing system ○ Callbacks ○ High-Order functions
  • 3. Inversion Of Control def service(s: String): Future[String] = future { s.toUpperCase } val foo = service(“foo”) val FOO = Await.result(foo, Duration.Inf) println(FOO + “ - bar”) service(“foo”).onSuccess { case res => println(res + “ - bar”) } Not IoC: full control of program flow IoC: scala.concurrent._ will run your code
  • 4. Dependency Injection ● A form of IoC where you relinquish the object creation/initialisation logic class Manager { val serviceOne = new ServiceOneImpl() val serviceTwo = new ServiceTwoImpl() def tx() { val id = serviceOne.fetch() serviceTwo.store(id) // ... } } object ManagerFactory { val Instance = new Manager( new ServiceOneImpl(), new ServiceTwoImpl() ) } class Manager( private val serviceOne: ServiceOne, private val serviceTwo: ServiceTwo ) { def tx() { … } }
  • 5. Dependency Injection ● Writing Factories is boring ● IoC containers ○ Spring Framework ○ Google Guice ○ Google Dagger ○ “The Cake Pattern” ○ ScalDI
  • 6. The Cake Pattern ● Advertised as the Scala way to do DI natively without any external framework ● Based on the concept of “self-type” ○ Constraints an impl of a type to be also an impl of the defined self types trait Foo { self: Bar with Baz => // the Foo type is going to assume that it is also a Bar and a Baz // ... }
  • 7. The Cake Pattern trait Shell {} trait Engine {} trait Car { self: Shell with Engine => } trait RenaultShell extends Shell {} trait NissanEngine extends Engine {} trait NissanShell extends Shell {} class RenaultScenic extends Car with RenaultShell with NissanEngine {} class NissanQashqai extends Car with NissanShell with NissanEngine {}
  • 8. The Cake Pattern ● First introduced by Odersky as the main modularization tool for the scalac/scala toolset [1] ● Further evangelized by Boner on his blog [2] ● Easy cookbook on the Cake Solution blog [3]
  • 9. The Cake Pattern Let’s use it to build a simple app with this structure: UserService UserDao MongoDB PostGres
  • 10. The Cake Pattern Like: ● No need of a IoC framework ● All your deps are checked at compile time Don’t like: ● Lots of boilerplate code ● On complex layouts is hard to see what the deps of a module are ● Introduces ‘hard’ concepts of the Scala type system ● Hard to get it right ● All these traits will slow down compilation time
  • 11. The Cake Pattern Truth is that people will start to give up on it pretty soon shortcutting to abominations like: trait MyServiceImpl extends MyService with DependencyA with DependencyB with DependencyC with DependencyD with DependencyE with DependencyF with DependencyG ...
  • 12. The Cake Pattern Current Production code in GILT: object Application extends Journal with Autocomplete with ProductLookSearch with SaleSearch with CategorySearch with AgeAndGenderSearch with HealthCheck with RuntimeEnvironment with Prefetch
  • 13. The Cake Pattern trait RuntimeEnvironment extends Environment override val search = ??? override val searchEventPublisher = ??? override val users = ??? override val sales = ??? override val ruleSets = ??? override val productLooksCache = ??? override val productDetailsCache = ??? override val externalProductsCache = ??? override val taxonomiesCache = ??? override val skuJournalsCache = ??? override val publicBrandsCache = ??? override val ruleSetsCache = ??? override val salesCache = ??? override val brandPromotions = ??? override val personalizer = ??? override val kafkaUtil = ??? override val benefitsCache = ??? override val hopperSales = ??? override val redirectClient = ??? override val preferences: Preferences = ??? // … more !! Who is depending on what ?
  • 14. The Cake Pattern trait SaleSearch extends SearchController with ResponseHelper with RedirectHelper with PilHelper with HopperHelper with SaleHelper with ExternalProductViewHelper with PageComponentsHelper with TopOfFunnelHelper with AbTestHelper { self: Environment => // WTF! // Stuff popping out from nowhere } ● On what SaleSearch really depends on? ● We basically flattened the dependency graph!!
  • 15. The Cake Pattern ● Hard to get it right even for Odersky & Co. ● Just happened on scala-internals ML: https://groups.google.com/forum/#!search/scala-internals$20EECOLOR/scala-internals/Z0kV6iDam0c/-09cDMEz754J “I do have some opinions about the trait you linked. I think it's design is flawed. Take for example it's base definition: trait Typechecker extends SymbolTable with Printers with Positions with CompilationUnits with QuasiquotesImpl When I read such a type my mind goes something like this: So Typechecker is a SymbolTable with Printers and Positions and CompilationUnits and QuasiquotesImpl. That instantly sends me to a place that I don't like….” “Here we have a peculiar consequence of using the cake pattern. Scalac's codebase illustrates this on a number of occasions as well.”
  • 16. The Cake Pattern // in Implicits.scala trait Implicits { self: Analyzer => // in Analyzer.scala trait Analyzer extends AnyRef with Contexts with Namers with Typers with Infer with Implicits with EtaExpansion with SyntheticMethods with Unapplies with Macros with NamesDefaults with TypeDiagnostics with ContextErrors with StdAttachments with AnalyzerPlugins
  • 17. The Cake Pattern ● No control over initialization logic ○ Is not part of the DI definition but is a nice to have ○ With Cake you need to code it yourself ○ Could be problematic due to trait linearization ● Let’s see how it could happen ...
  • 18. ScalDI ● IMHO the Cake pattern is ○ too much hassle ○ hard to get it right ○ badly implemented could cripple your code base ● Alternatives? ● Be disciplined and write your factory objects ● ScalDI ○ Small and simple ○ Easier to use and to understand
  • 19. ScalDI Simple: only 3 concepts ● Injector ○ A container for your bindings ● Module ○ A place where you define the bindings using a nice DSL ○ It is an Injector ● Injectable ○ Provides a DSL to inject dependencies
  • 20. ScalDI Simple example class DefaultServiceImpl(implicit inj: Injector) extends Service with Injectable { val conf = inject [String] (identified by “service.configuration”) def run() = { println(s”conf: $conf”) } } class ServiceModule extends Module { binding indentifiedBy “service.configuration” to “jdbc://mysql/mydb” bind [Service] to new DefaultServiceImpl // bind [Service] toNonLazy DefaultServiceImpl } class MyApp(implicit inj: Injector) extends Injectable { private val service: Service = inject [Service] }
  • 21. ScalDI Module composition val storeModule = new Module { bind [UserDao] to new PsqlUserDaoImpl() bind [OrderDao] to new MongoDbOrderDaoImpl() } val cacheModule = new Module { bind [UserCache] to new LRUUserCacheImpl() bind [OrderCache] to new TTLOrderCacheImpl() } val appModule = storeModule :: cacheModule // then in test ... val mocks = new Module { bind [OrderDao] to new MockOrderDaoImpl() } val appModule = mocks :: appModule // will redefine OrderDao with a mock
  • 22. ScalDI Constructor injection class ServiceImpl(dao: Dao, cache: Cache) extends Service { // … } val module = new Module { bind [Service] to injected [ServiceImpl] } // after macro expansion val module = new Module { bind [Service] to new ServiceImpl( dao = inject[Dao], cache = inject[Cache] ) }
  • 23. ScalDI You can inject everything! val myModule = new Module { binding identifiedBy “greetings” to “Hello World!” binding identifiedBy “adder” to ((a: Int, b: Int) => a + b) } class Consumer(implicit inj: Injector) extends Injectable { val greet: String = inject [String] (identifiedBy “greetings”) val adder = inject [(Int, Int) => Int] (identifiedBy “adder”) }
  • 24. ScalDI Conditional injection val daoModule = new Module { bind [Dao] when (inDevMode or inTestMode) to new H2Dao() bind [Dao] when to new PsqlDao() def inDevMode = !inTestMode && !inProdMode def inTestMode = System.getProperty(...) def inProdMode = System.getProperty(...) }
  • 25. ScalDI Lifecycle! trait Cache { def start() def stop() } class CacheImpl extends Cache { def start() = { fetchAll() } def stop() = { … } } val app = new Module { // will init all your bindings bind [Cache] to new CacheImpl() initWith { _.start() }, destroyWith { _.stop() } } app.destroy() // will invoke all your destroy logics
  • 26. ScalDI + Play Can inject into Play controllers! // with ScalDI a Controller is not an Object!! // just remember to add a @ in the routes file class MyController(implicit inj: Injector) extends Controller with Injectable { private val serviceOne = inject [ServiceOne] private val serviceTwo = inject [ServiceTwo] def index = Action { Ok(serviceOne.run(serviceTwo.run())) } }
  • 27. ScalDI + Akka Inject Props and ActorRef class ParentActor(implicit inj: Injector) extends Actor with AkkaInjectable { val childActorProps = injectActorProps [ChildActor] val friendActorRef = injectActorRef [FriendActor] def receive = { case Spawn => context.actorOf(childActorProps) case Greet => friendActorRef ! Hello } }
  • 28. ScalDI + Play = DEMO!
  • 29. ScalDI I like: ● Easy ● Nice DSL to inject/define dependencies ● Different forms of injections ● Handles lifecycle ● Supports Play and Akka Don’t like: ● Still somewhat intrusive
  • 30. EOF