ݺߣ

ݺߣShare a Scribd company logo
МИХАИЛ
КРЕСТЬЯНИНОВ
АНДРОИД РАЗРАБОТЧИК
t.me/krest_m
DAGGER’A?
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ
NO MORE!
2
DAGGSTASY
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
АГЕНДА
▸DEPENDENCY INJECTION
▸ИНТРО:
▸LIGHTSABER vs KODEIN vs TOOTHPICK
LIGHTSABER
KODEIN
TOOTHPICK
3
INVERSION
OF
CONTROL
DEPENDENCY
INVERSION
PRINCIPLE
DEPENDENCY
INJECTION
"HOLLYWOOD PRINCIPLE: DON'T CALL US, WE'LL CALL YOU"
DEPENDENCY INJECTION - реализация DIP.
Инструмент передачи классу его
зависимостей.
4
"HOLLYWOOD PRINCIPLE”:
DON'T CALL US, WE'LL CALL YOU
5
"HOLLYWOOD PRINCIPLE”:
DON'T CALL US, WE'LL CALL YOU
5
class Tweeter {
fun tweet(message: String) {
val api: TweeterApi = TweeterApi()
api.sendTweet(message)
}
}
"HOLLYWOOD PRINCIPLE”:
DON'T CALL US, WE'LL CALL YOU
5
class Tweeter {
fun tweet(message: String) {
val api: TweeterApi = TweeterApi()
api.sendTweet(message)
}
}
"HOLLYWOOD PRINCIPLE”:
DON'T CALL US, WE'LL CALL YOU
class Tweeter(val api: TweeterApi) {
fun tweet(message: String) {
api.sendTweet(message)
}
}
6
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
ТЕКУЩАЯ СИТУАЦИЯ НА РЫНКЕ
7
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
ТЕКУЩАЯ СИТУАЦИЯ НА РЫНКЕ
DAGGER MONOPOLY
7
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
АГЕНДА
▸DEPENDENCY INJECTION
▸ИНТРО:
▸LIGHTSABER vs KODEIN vs TOOTHPICK
LIGHTSABER
KODEIN
TOOTHPICK
8
LIGHTSABER
MICHAELROCKS/LIGHTSABER
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
9
LIGHTSABER
MICHAELROCKS/LIGHTSABER
10
▸ Текущая версия
0.9.0-beta
▸ Мотивация
▸ Главная особенность
LIGHTSABER
MICHAELROCKS/LIGHTSABER
11
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
Лёгкий и быстрый DI
& Compile Time
& Не зависящий от APT
LIGHTSABER
MICHAELROCKS/LIGHTSABER
12
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
Использует патчинг
байткода вместо
Annotation Processing
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
АГЕНДА
▸DEPENDENCY INJECTION
▸ИНТРО:
▸LIGHTSABER vs KODEIN vs TOOTHPICK
LIGHTSABER
KODEIN
TOOTHPICK
13
KODEIN
SALOMONBRYS/KODEIN
14
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
KODEIN
SALOMONBRYS/KODEIN
15
▸ Текущая версия
4.0.0
▸ Мотивация
▸ Главная особенность
KODEIN
SALOMONBRYS/KODEIN
16
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
DSL-декларативный DI
& Идиоматичный
& Debuggable + Docs
KODEIN
SALOMONBRYS/KODEIN
17
Простота в использовании
& Kotlin friendly
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
АГЕНДА
▸DEPENDENCY INJECTION
▸ИНТРО:
▸LIGHTSABER vs KODEIN vs TOOTHPICK
LIGHTSABER
KODEIN
TOOTHPICK
18
TOOTHPICK
STEPHANENICOLAS/TOOTHPICK
19
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
TOOTHPICK
STEPHANENICOLAS/TOOTHPICK
20
▸ Текущая версия
1.0.7
▸ Мотивация
▸ Главная особенность
TOOTHPICK
STEPHANENICOLAS/TOOTHPICK
21
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
Проще, чем Dagger
& Тестируемость
& Scope
TOOTHPICK
STEPHANENICOLAS/TOOTHPICK
22
Тестируемость из коробки
& 2 DAGs
▸ Текущая версия
▸ Мотивация
▸ Главная особенность
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
АГЕНДА
▸DEPENDENCY INJECTION
▸ИНТРО:
▸LIGHTSABER vs KODEIN vs TOOTHPICK
LIGHTSABER
KODEIN
TOOTHPICK
23
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A? 24
LIGHTSABER
VS
KODEIN
VS
TOOTHPICK
▸ОСНОВНЫЕ ПРИНЦИПЫ
▸ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸SCOPES
▸ТЕСТИРОВАНИЕ
LIGHTSABER VS KODEIN VS TOOTHPICK 25
КРИТЕРИИ
ОСНОВНЫЕ ПРИНЦИПЫ
LIGHTSABER
26
ОСНОВНЫЕ ПРИНЦИПЫ
LIGHTSABER
26
ОСНОВНЫЕ ПРИНЦИПЫ
LIGHTSABER
▸Lightsaber работает на
основе JSR 330
26
ОСНОВНЫЕ ПРИНЦИПЫ
LIGHTSABER
▸Lightsaber работает на
основе JSR 330
▸Аннотация
вешается на конструктор,
поле или метод класса
@Inject
26
LIGHTSABER
ОСНОВНЫЕ ПРИНЦИПЫ
val injector = Lightsaber.get()
.createInjector(
AppComponent(app = this)
)
injector.injectMembers(this)
27
LIGHTSABER
ОСНОВНЫЕ ПРИНЦИПЫ
val injector = Lightsaber.get()
.createInjector(
AppComponent(app = this)
)
injector.injectMembers(this)
28
LIGHTSABER
ОСНОВНЫЕ ПРИНЦИПЫ
val injector = Lightsaber.get()
.createInjector(
AppComponent(app = this)
)
injector.injectMembers(this)
29
val injector = Lightsaber.get()
.createInjector(
AppComponent(app = this)
)
injector.injectMembers(this)
LIGHTSABER
ОСНОВНЫЕ ПРИНЦИПЫ 30
ОСНОВНЫЕ ПРИНЦИПЫ
KODEIN
31
ОСНОВНЫЕ ПРИНЦИПЫ
KODEIN
31
ОСНОВНЫЕ ПРИНЦИПЫ
KODEIN
▸Лёгкий старт
31
ОСНОВНЫЕ ПРИНЦИПЫ
KODEIN
▸Лёгкий старт
▸Java-only @Inject
31
ОСНОВНЫЕ ПРИНЦИПЫ
KODEIN
▸Лёгкий старт
▸Java-only
▸Runtime-проверка графа
@Inject
31
ОСНОВНЫЕ ПРИНЦИПЫ
KODEIN
▸Лёгкий старт
▸Java-only
▸Runtime-проверка графа
▸Kodein Kotlin
@Inject
31
ОСНОВНЫЕ ПРИНЦИПЫ
val kodein = Kodein {
import(appModule(this@App))
}
val injector = KodeinInjector()
val prefs: SharedPreferences by injector.instance()
override fun onCreate() {
super.onCreate()
injector.inject(kodein)
}
32
KODEIN
ОСНОВНЫЕ ПРИНЦИПЫ
val kodein = Kodein {
import(appModule(this@App))
}
val injector = KodeinInjector()
val prefs: SharedPreferences by injector.instance()
override fun onCreate() {
super.onCreate()
injector.inject(kodein)
}
33
KODEIN
ОСНОВНЫЕ ПРИНЦИПЫ
val kodein = Kodein {
import(appModule(this@App))
}
val injector = KodeinInjector()
val prefs: SharedPreferences by injector.instance()
override fun onCreate() {
super.onCreate()
injector.inject(kodein)
}
34
KODEIN
ОСНОВНЫЕ ПРИНЦИПЫ
val kodein = Kodein {
import(appModule(this@App))
}
val injector = KodeinInjector()
val prefs: SharedPreferences by injector.instance()
override fun onCreate() {
super.onCreate()
injector.inject(kodein)
}
35
KODEIN
ОСНОВНЫЕ ПРИНЦИПЫ
val kodein = Kodein {
import(appModule(this@App))
}
val injector = KodeinInjector()
val prefs: SharedPreferences by injector.instance()
override fun onCreate() {
super.onCreate()
injector.inject(kodein)
}
36
KODEIN
ОСНОВНЫЕ ПРИНЦИПЫ
val kodein = Kodein {
import(appModule(this@App))
}
val injector = KodeinInjector()
val prefs: SharedPreferences by injector.instance()
override fun onCreate() {
super.onCreate()
injector.inject(kodein)
}
37
KODEIN
ОСНОВНЫЕ ПРИНЦИПЫ 38
TOOTHPICK
ОСНОВНЫЕ ПРИНЦИПЫ 38
TOOTHPICK
ОСНОВНЫЕ ПРИНЦИПЫ 38
TOOTHPICK
▸Toothpick работает на
основе JSR 330
ОСНОВНЫЕ ПРИНЦИПЫ 38
TOOTHPICK
▸Toothpick работает на
основе JSR 330
▸Аннотация
вешается на конструктор,
поле или метод класса
@Inject
ОСНОВНЫЕ ПРИНЦИПЫ
val scope = Toothpick.openScopes(app, this)
scope.installModules(ActivityModule(this))
Toothpick.inject(this, scope)
39
TOOTHPICK
ОСНОВНЫЕ ПРИНЦИПЫ
val scope = Toothpick.openScopes(app, this)
scope.installModules(ActivityModule(this))
Toothpick.inject(this, scope)
40
TOOTHPICK
ОСНОВНЫЕ ПРИНЦИПЫ
val scope = Toothpick.openScopes(app, this)
scope.installModules(ActivityModule(this))
Toothpick.inject(this, scope)
41
TOOTHPICK
ОСНОВНЫЕ ПРИНЦИПЫ
val scope = Toothpick.openScopes(app, this)
scope.installModules(ActivityModule(this))
Toothpick.inject(this, scope)
42
TOOTHPICK
▸ОСНОВНЫЕ ПРИНЦИПЫ
▸ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸SCOPES
▸ТЕСТИРОВАНИЕ
LIGHTSABER VS KODEIN VS TOOTHPICK 43
КРИТЕРИИ
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 44
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 44
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸Constructors
44
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸Constructors
▸Module
44
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸Constructors
▸Module
▸Component
44
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 45
@Module
class MainModule(val app: Application) {
@Provides
@Singleton
@Named(Tag.APPLICATION_CONTEXT)
private fun context(): Context = app
@Provides
private fun presenter(repo: Repository): Presenter
= PresenterImpl(repo)
}
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Module
class MainModule(val app: Application) {
@Provides
@Singleton
@Named(Tag.APPLICATION_CONTEXT)
private fun context(): Context = app
@Provides
private fun presenter(repo: Repository): Presenter
= PresenterImpl(repo)
}
46
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Module
class MainModule(val app: Application) {
@Provides
@Singleton
@Named(Tag.APPLICATION_CONTEXT)
private fun context(): Context = app
@Provides
private fun presenter(repo: Repository): Presenter
= PresenterImpl(repo)
}
47
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Module
class MainModule(val app: Application) {
@Provides
@Singleton
@Named(Tag.APPLICATION_CONTEXT)
private fun context(): Context = app
@Provides
private fun presenter(repo: Repository): Presenter
= PresenterImpl(repo)
}
48
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Component
class AppComponent(
val app: Application
) {
@Provides
fun provideAppModule()
= AppModule(app)
}
49
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Component
class AppComponent(
val app: Application
) {
@Provides
fun provideAppModule()
= AppModule(app)
}
50
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Component
class AppComponent(
val app: Application
) {
@Provides
fun provideAppModule()
= AppModule(app)
}
51
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 52
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸ Lazy injections
@Inject
lateinit var presenter: Lazy<Presenter>
52
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸ Lazy injections
@Inject
lateinit var presenter: Lazy<Presenter>
52
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Inject
lateinit var presenter: Provider<Presenter>
▸ Lazy injections
@Inject
lateinit var presenter: Lazy<Presenter>
52
▸ Provider injections
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Inject
lateinit var presenter: Provider<Presenter>
▸ Lazy injections
@Inject
lateinit var presenter: Lazy<Presenter>
52
▸ Provider injections
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
@Inject
lateinit var presenter: Provider<Presenter>
▸ Lazy injections
@Inject
lateinit var presenter: Lazy<Presenter>
52
▸ Provider injections
▸ Custom Scope & Qualifiers
LIGHTSABER
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 53
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 53
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸Modules, Modules, Modules…
53
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
Kodein.Module {
import(module = sampleModule)
bind<Context>(Tag.APP_CONTEXT) with singleton {
app
}
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(Tag.APP_CONTEXT),
sharedPreferences = instance()
)
}
}
54
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
Kodein.Module {
import(module = sampleModule)
bind<Context>(Tag.APP_CONTEXT) with singleton {
app
}
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(Tag.APP_CONTEXT),
sharedPreferences = instance()
)
}
}
55
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
Kodein.Module {
import(module = sampleModule)
bind<Context>(Tag.APP_CONTEXT) with singleton {
app
}
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(Tag.APP_CONTEXT),
sharedPreferences = instance()
)
}
}
56
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
Kodein.Module {
import(module = sampleModule)
bind<Context>(Tag.APP_CONTEXT) with singleton {
app
}
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(Tag.APP_CONTEXT),
sharedPreferences = instance()
)
}
}
57
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
Kodein.Module {
import(module = sampleModule)
bind<Context>(Tag.APP_CONTEXT) with singleton {
app
}
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(Tag.APP_CONTEXT),
sharedPreferences = instance()
)
}
}
58
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
Kodein.Module {
import(module = sampleModule)
bind<Context>(Tag.APP_CONTEXT) with singleton {
app
}
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(Tag.APP_CONTEXT),
sharedPreferences = instance()
)
}
}
59
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 60
KODEIN
▸ Factory
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind<RandomUtil>() with factory { num: Int ->
FakeRandom(num)
}
60
KODEIN
▸ Factory
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind<RandomUtil>() with factory { num: Int ->
FakeRandom(num)
}
60
KODEIN
▸ Provider
▸ Factory
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind<RandomUtil>() with factory { num: Int ->
FakeRandom(num)
}
bind<RandomUtil>() with provider {
FakeRandom(2)
}
60
KODEIN
▸ Provider
▸ Factory
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind<RandomUtil>() with factory { num: Int ->
FakeRandom(num)
}
bind<RandomUtil>() with provider {
FakeRandom(2)
}
60
KODEIN
▸ Provider
▸ And many others
▸ Factory
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind<RandomUtil>() with factory { num: Int ->
FakeRandom(num)
}
bind<RandomUtil>() with provider {
FakeRandom(2)
}
60
KODEIN
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 61
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 61
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸Constructors
61
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸Constructors
▸Module
61
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
class Module(val app: Application) : Module() {
init {
bind(Context ::class.java)
.withName(Tag.APP_CONTEXT)
.toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
}
}
62
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
class Module(val app: Application) : Module() {
init {
bind(Context ::class.java)
.withName(Tag.APP_CONTEXT)
.toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
}
}
63
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
class Module(val app: Application) : Module() {
init {
bind(Context ::class.java)
.withName(Tag.APP_CONTEXT)
.toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
}
}
64
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
class Module(val app: Application) : Module() {
init {
bind(Context ::class.java)
.withName(Tag.APP_CONTEXT)
.toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
}
}
65
TOOTHPICK
class Module(val app: Application) : Module() {
init {
bind(Context ::class.java)
.withName(Tag.APP_CONTEXT)
.toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
}
}
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ 66
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind(Interface ::class.java)
.to****(Class ::class.java)
67
TOOTHPICK
ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
bind(Interface ::class.java)
.to****(Class ::class.java)
68
TOOTHPICK
▸ОСНОВНЫЕ ПРИНЦИПЫ
▸ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸SCOPES
▸ТЕСТИРОВАНИЕ
LIGHTSABER VS KODEIN VS TOOTHPICK 69
КРИТЕРИИ
SCOPES 70
LIGHTSABER
SCOPES 70
LIGHTSABER
SCOPES
▸Аннотации по JSR 330
70
LIGHTSABER
SCOPES
▸Аннотации по JSR 330
70
LIGHTSABER
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
SCOPES
▸Аннотации по JSR 330
70
LIGHTSABER
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
@Module
class AppModule(val app: Application) {
@Provides
@Singleton
private fun context(): Context = app
}
SCOPES 71
LIGHTSABER
SCOPES
@Singleton
class PresenterImpl()
72
LIGHTSABER
SCOPES 73
KODEIN
SCOPES 73
KODEIN
SCOPES
▸Bindigs & Module
73
KODEIN
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(APP_CONTEXT),
api = instance()
)
}
SCOPES
▸Bindigs & Module
73
KODEIN
bind<Repository>() with singleton {
RepositoryImpl(
context = instance(APP_CONTEXT),
api = instance()
)
}
SCOPES
▸Bindigs & Module
73
KODEIN
SCOPES 74
TOOTHPICK
SCOPES 74
TOOTHPICK
SCOPES
Место, где выполняются
инъекции
SCOPE
74
TOOTHPICK
SCOPES
val scope = Toothpick.openScope(this)
scope.installModules(AppModule(this))
Toothpick.inject(this, scope)
Toothpick.closeScope(this)
Место, где выполняются
инъекции
SCOPE
74
TOOTHPICK
SCOPES
val scope = Toothpick.openScope(this)
scope.installModules(AppModule(this))
Toothpick.inject(this, scope)
Toothpick.closeScope(this)
Место, где выполняются
инъекции
SCOPE
74
TOOTHPICK
val scope = Toothpick.openScope(this)
scope.installModules(AppModule(this))
Toothpick.inject(this, scope)
Toothpick.closeScope(this)
SCOPES
Место, где выполняются
инъекции
SCOPE
75
TOOTHPICK
SCOPES
SCOPE BINDINGSModule
76
TOOTHPICK
val scope = Toothpick.openScope(this)
scope.installModules(AppModule(this))
Toothpick.inject(this, scope)
Toothpick.closeScope(this)
SCOPES 77
TOOTHPICK
SCOPES
APPLICATION
SCOPE
ACTIVITY
SCOPE
FRAGMENT 2
SCOPE
FRAGMENT 1
SCOPE
FRAGMENT 3
SCOPE
77
TOOTHPICK
bind(Context ::class.java).toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
SCOPES 78
TOOTHPICK
bind(Context ::class.java).toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
SCOPES 78
TOOTHPICK
bind(Context ::class.java).toInstance(app)
bind(Repository ::class.java)
.to(RepositoryImpl ::class.java)
.singletonInScope()
SCOPES 79
TOOTHPICK
SCOPES 80
TOOTHPICK
SCOPES
▸ Аннотации по JSR 330
80
TOOTHPICK
SCOPES
▸ Аннотации по JSR 330
▸ Кастомные аннотации
80
TOOTHPICK
SCOPES
▸ Аннотации по JSR 330
▸ Кастомные аннотации
@javax.inject.Scope
@Documented
@Retention(AnnotationRetention.RUNTIME)
annotation class PresenterScope
80
TOOTHPICK
SCOPES
▸ Аннотации по JSR 330
▸ Кастомные аннотации
val scope = Toothpick.openScopes(
application,
PresenterScope ::class.java,
this)
@javax.inject.Scope
@Documented
@Retention(AnnotationRetention.RUNTIME)
annotation class PresenterScope
80
TOOTHPICK
SCOPES
▸ Аннотации по JSR 330
▸ Кастомные аннотации
val scope = Toothpick.openScopes(
application,
PresenterScope ::class.java,
this)
@javax.inject.Scope
@Documented
@Retention(AnnotationRetention.RUNTIME)
annotation class PresenterScope
80
TOOTHPICK
▸ОСНОВНЫЕ ПРИНЦИПЫ
▸ДЕКЛАРАЦИЯ ЗАВИСИМОСТЕЙ
▸SCOPES
▸ТЕСТИРОВАНИЕ
LIGHTSABER VS KODEIN VS TOOTHPICK 81
КРИТЕРИИ
ТЕСТИРОВАНИЕ 82
LIGHTSABER
ТЕСТИРОВАНИЕ 82
LIGHTSABER
ТЕСТИРОВАНИЕ
▸ Нужно просто переопределять
все необходимые модули в
тестах
82
LIGHTSABER
ТЕСТИРОВАНИЕ
▸ Нужно просто переопределять
все необходимые модули в
тестах
@Module
class Module {
@Provides
private fun presenter(): MainPresenter
= FakePresenter()
}
82
LIGHTSABER
ТЕСТИРОВАНИЕ 83
KODEIN
ТЕСТИРОВАНИЕ 83
KODEIN
ТЕСТИРОВАНИЕ
▸ Флаг allowOverride = true
83
KODEIN
ТЕСТИРОВАНИЕ
class TestApp : App() {
override val kodein: Kodein by lazy {
Kodein {
import(
module = appModule(this@TestApp),
allowOverride = true
)
constant("TEST", overrides = true) with 4L
}
}
}
▸ Флаг allowOverride = true
83
KODEIN
ТЕСТИРОВАНИЕ
class TestApp : App() {
override val kodein: Kodein by lazy {
Kodein {
import(
module = appModule(this@TestApp),
allowOverride = true
)
constant("TEST", overrides = true) with 4L
}
}
}
▸ Флаг allowOverride = true
83
KODEIN
ТЕСТИРОВАНИЕ 84
TOOTHPICK
ТЕСТИРОВАНИЕ 84
TOOTHPICK
ТЕСТИРОВАНИЕ
▸Киллер-фича
84
TOOTHPICK
ТЕСТИРОВАНИЕ
▸Киллер-фича
@Mock
private lateinit var repository: Repository
@Rule
@JvmField
var toothPickRule = ToothPickRule(this, app)
84
TOOTHPICK
ТЕСТИРОВАНИЕ
▸Киллер-фича
@Mock
private lateinit var repository: Repository
@Rule
@JvmField
var toothPickRule = ToothPickRule(this, app)
84
TOOTHPICK
ТЕСТИРОВАНИЕ
▸Киллер-фича
@Mock
private lateinit var repository: Repository
@Rule
@JvmField
var toothPickRule = ToothPickRule(this, app)
85
TOOTHPICK
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A? 86
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A? 86
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Брат по духу с Dagger
86
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Брат по духу с Dagger
▸Нет боли с APT
86
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Брат по духу с Dagger
▸Нет боли с APT
▸Вербозный
86
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Брат по духу с Dagger
▸Нет боли с APT
▸Вербозный
▸Неудобный для тестов
86
LIGHTSABER.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Брат по духу с Dagger
▸Нет боли с APT
▸Вербозный
▸Неудобный для тестов
▸Нерелизная версия
86
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
KODEIN.CONCLUSION()
87
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
KODEIN.CONCLUSION()
87
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
KODEIN.CONCLUSION()
▸Действительно лёгкий
87
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
KODEIN.CONCLUSION()
▸Действительно лёгкий
▸Kotlin friendly
87
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
KODEIN.CONCLUSION()
▸Действительно лёгкий
▸Kotlin friendly
▸Runtime-проверка графа
87
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
KODEIN.CONCLUSION()
▸Действительно лёгкий
▸Kotlin friendly
▸Runtime-проверка графа
▸С тестированием уже
легче
87
TOOTHPICK.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A? 88
TOOTHPICK.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A? 88
TOOTHPICK.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Детальный Scope
88
TOOTHPICK.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Детальный Scope
▸Бро для тестов
88
TOOTHPICK.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Детальный Scope
▸Бро для тестов
▸Compile + Runtime-проверка
графа
88
TOOTHPICK.CONCLUSION()
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
▸Детальный Scope
▸Бро для тестов
▸Compile + Runtime-проверка
графа
▸Нельзя сказать, что они достигли
простоты по сравнению с Dagger
88
ЕСТЬ ЛИ ЖИЗНЬ БЕЗ DAGGER’A?
FINAL
89
Simplicity Scope Tests Perf
Lightsaber
Kodein
Toothpick
Dagger
СПАСИБО!
OMG! NOW I NEED A
KODEIN DOZE..
special thanks to @georgeci
Ligthsaber
Kodein
Tootpick
git.io/v7cw8
git.io/v7cwY
git.io/v7cwg
Ad

Recommended

Feature toggles в процессе подбора, Алексей Ульенков СберТех
Feature toggles в процессе подбора, Алексей Ульенков СберТех
Сбертех | SberTech
Чистая архитектура, Артур Бадретдинов АБЦТ
Чистая архитектура, Артур Бадретдинов АБЦТ
Сбертех | SberTech
Модульная архитектура Сбербанк Онлайн, Владимир Озеров и Александр Черушнико...
Модульная архитектура Сбербанк Онлайн, Владимир Озеров и Александр Черушнико...
Сбертех | SberTech
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Сбертех | SberTech
Один день из жизни iOs разработчика, Александр Сычёв Rambler&Co
Один день из жизни iOs разработчика, Александр Сычёв Rambler&Co
Сбертех | SberTech
Аспекты применения Agile для крупных хранилищ данных
Аспекты применения Agile для крупных хранилищ данных
Сбертех | SberTech
Internet of things
Internet of things
Сбертех | SberTech
Биометрия и платежи
Биометрия и платежи
Сбертех | SberTech
2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing
Search Engine Journal
Storytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design Process
Chiara Aliotta
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
OECD Directorate for Financial and Enterprise Affairs
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
SocialHRCamp
2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
Skeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC

More Related Content

Featured (20)

2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing
Search Engine Journal
Storytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design Process
Chiara Aliotta
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
OECD Directorate for Financial and Enterprise Affairs
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
SocialHRCamp
2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
Skeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC
2024 Trend Updates: What Really Works In SEO & Content Marketing
2024 Trend Updates: What Really Works In SEO & Content Marketing
Search Engine Journal
Storytelling For The Web: Integrate Storytelling in your Design Process
Storytelling For The Web: Integrate Storytelling in your Design Process
Chiara Aliotta
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
SocialHRCamp
2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray

Есть ли жизнь без Dagger'a, Михаил Крестьянинов Avito