Slide 1

Slide 1 text

DI WITH KOTLIN KOTLIN MEETUP #1 2016.07.05 Hiroshi Kurokawa (@hydrakecat)

Slide 2

Slide 2 text

WHAT’S DI? ▸ Dependency Injection ▸ Client takes advantage of a Service ▸ Injector provides a concrete implementation of the Service to the Client Client Service ServiceImpl

Slide 3

Slide 3 text

WHAT’S DI? ▸ Dependency Injection ▸ Client takes advantage of a Service ▸ Injector provides a concrete implementation of the Service to the Client Client Service ServiceImpl

Slide 4

Slide 4 text

WHAT’S DI? ▸ Dependency Injection ▸ Client takes advantage of a Service ▸ Injector provides a concrete implementation of the Service to the Client Client Service ServiceImpl Injector

Slide 5

Slide 5 text

WHAT’S DI? ▸ Dependency Injection ▸ Client takes advantage of a Service ▸ Injector provides a concrete implementation of the Service to the Client Client Service ServiceImpl Injector

Slide 6

Slide 6 text

ADVANTAGES ▸ Decoupling of components ▸ Model layer doesn’t need to know about infrastructure layers ▸ Less boilerplates ▸ Configurable ▸ Unit Testing ▸ Production/Development Release

Slide 7

Slide 7 text

3 APPROACHES TO ACHIEVE DI WITH JAVA ▸ DI Container ▸ Constructor ▸ Setter (See http://martinfowler.com/articles/injection.html)

Slide 8

Slide 8 text

4 APPROACHES TO ACHIEVE DI WITH KOTLIN ▸ DI Container ▸ Constructor ▸ Setter ▸ Interface with default implementation

Slide 9

Slide 9 text

▸ DI Container ▸ Constructor ▸ Setter ▸ Interface with default implementation 4 APPROACHES TO ACHIEVE DI WITH KOTLIN

Slide 10

Slide 10 text

1. Java DI Container ▸ Spring ▸ Dagger 1&2 ▸ so on … 2. Kotlin DI Container ‣ Injekt ‣ Kodein 3. Interface with default implementation 3 WAYS TO DO DI

Slide 11

Slide 11 text

1. JAVA DI CONTAINER ▸ Spring ▸ Guice ▸ Dagger 1 & 2
 needs annotation processor (kapt) @Component(modules = arrayOf(DripCoffeeModule::class) ) interface CoffeeShop { fun maker() : CoffeeMaker } class CoffeeMaker { @Inject lateinit var heater: Heater @Inject lateinit var pump: Pump }

Slide 12

Slide 12 text

1. JAVA DI CONTAINER ▸ Pros ▸ Based on JSR-330 ▸ Many frameworks ▸ Cons ▸ Kapt is not stable yet ▸ Compile/runtime error can be complicated ▸ Interoperation with Java might be required

Slide 13

Slide 13 text

2. KOTLIN DI CONTAINER class CoffeeMaker() { val injector = Injector() private val heater: Heater by injector.instance() private val pump: Pump by injector.instance() … } ‣ In Kotlin, you can delegate getter of properties

Slide 14

Slide 14 text

‣ Kodein 1. Describe dependencies val dripCoffee = Kodein { bind() with provider { ElectricHeater() } bind() with provider { Thermosiphon(instance()) } bind() with provider { instance() } } 2. KOTLIN DI CONTAINER

Slide 15

Slide 15 text

class CoffeeMaker() { val injector = KodeinInjector() private val heater: Heater by injector.instance() private val pump: Pump by injector.instance() … } fun main(args: Array) { val maker = CoffeeMaker() maker.injector.inject(dripCoffee) maker.brew() } ‣ Kodein 1. Describe dependencies 2. Delegate to KodeinInjector 2. KOTLIN DI CONTAINER

Slide 16

Slide 16 text

▸ Pros ▸ Factory can be used to provide a service! ▸ It’s hard with Java apt-based DI container ▸ Pure Kotlin ▸ Cons ▸ Possible runtime error ▸ Configuration could be cumbersome especially when dependencies are nested 2. KOTLIN DI CONTAINER

Slide 17

Slide 17 text

3. INTERFACE ▸ In Kotlin, interface can have default implementations ▸ By extending an interface, client can have an access to a service implementation ▸ “Minimal Cake Pattern” in Scala could be a good guide interface UsesCoffeeModule { val coffeeModule: CoffeeModule } interface MixInDripCoffee : UsesCoffeeModule { override val coffeeModule: CoffeeModule get() = DripCoffee() }

Slide 18

Slide 18 text

3. INTERFACE interface CoffeeMaker: UsesCoffeeModule { fun brew() { coffeeModule.heater().on() coffeeModule.pump().on() coffeeModule.pump().off() coffeeModule.heater().off() } } fun main(args: Array) { // With MixInDripCoffee interface, a DripCoffee is injected val maker = object : CoffeeMaker, MixInDripCoffee {} maker.brew()

Slide 19

Slide 19 text

3. INTERFACE ▸ Pros ▸ No configuration DSL ▸ Dependency is clear in the code ▸ No complicated runtime/compilation error ▸ Cons ▸ Not so flexible to configure

Slide 20

Slide 20 text

CONCLUSION ▸ There seems no de facto standard DI method in Kotlin yet ▸ Java DI container is probably the best choice for now ▸ If you’re willing to struggle with Kapt ;-) ▸ Minimal Cake Pattern would be great if you don’t need much flexible configuration

Slide 21

Slide 21 text

Thank you! Hiroshi Kurokawa (ࠇ઒ ༸) @hydrakecat https://github.com/hkurokawa https://speakerdeck.com/hkurokawa hydrakecat.hatenablog.jp