The goal was to talk about dependency injection, show advantages, disadvantages and how it works. (meetup BsAs Argentina November 2019 & devfest CDMX December 2019 )
player2 = Player2() fun start() { print("Start Match") player1.serve() player2.drive() } } fun main() { val match = TennisMatch() match.start() } Without dependency Injection
lot Coupled Code • Difficult to add new functionality • Infinite levels of Inheritance • Extends non abstract class • Base classes with hundreds of lines code.
Inversion. It consists of passing dependencies via constructor or setter to extract the task of creating modules out from other modules. Objects are instantiated somewhere else and passed as constructor attributes when creating the current object.
fun start() { print("Start Match") player1.serve() player2.drive() } } fun main() { val player1 = Player1() val player2 = Player2() val match = TennisMatch(player1, player2) match.start() } Constructor Injection
Player2 fun start() { print("Start Match") player1.serve() player2.drive() } } fun main() { val match = TennisMatch() match.player1 = Player1() match.player2 = Player2() match.start() } Field or Setter Injection
fun start() { print("Start Match") tennisPlayer1.shot() tennisPlayer2.shot() } } fun main() { val player1 = Player1() val player2 = Player2() val match = TennisMatch(player1, player2) match.start() }
can reuse those components. • We can just change the implementation of any object without having to make a lot of changes in our codebase, since that object instantiation resides in one place isolated and decoupled. • Detect smells related to class dependencies • Dependencies can be injected into a component: it is possible to inject mock implementations of these dependencies which makes testing easier.
create modules inside modules, there must be a place where those modules are instantiated. • Modules with huge constructors including lots of dependencies, code will become dirty and hard to read. • You can not to access the constructor of an activity
that is in charge of providing instances of the rest of modules and inject their dependencies. • Dagger 2 (Dagger-android :S) • Koin • Kodein-DI • Service Locator
graph • No Runtime Error • Performance & Easy debugging (I used to dagger 1) • Easy configuration of complex dependencies. • Scoped instances • Scalability • Simplifies access to shared instances • Supported by Google Why do I use Dagger 2 ?
@Suppress("UNCHECKED_CAST") override fun <T : ViewModel?> create(modelClass: Class<T>) = if (modelClass.isAssignableFrom(PlayersViewModel::class.java)) PlayersViewModel(getPlayersUseCase) as T else throw IllegalArgumentException("Unknown ViewModel class") }