Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Toothpick - A fresh approach to DI (Including ...
Search
Daniel Molinero Reguera
April 11, 2017
Programming
1
1.1k
Toothpick - A fresh approach to DI (Including Unit Testing)
Presented at Droidcon Boston 2017
Daniel Molinero Reguera
April 11, 2017
Tweet
Share
More Decks by Daniel Molinero Reguera
See All by Daniel Molinero Reguera
TP3 & KTP: Simple, fast, and boilerplate-free DI for Kotlin
dlemures
0
62
Toothpick - A fresh approach to DI - Short Version
dlemures
0
66
Toothpick Bad Practices 🙅 and Nice Tricks 👌
dlemures
0
100
Dart & Henson - Better Android Intents
dlemures
1
230
Toothpick - A fresh approach to DI
dlemures
0
130
Toothpick & Dependency Injection
dlemures
1
2k
Other Decks in Programming
See All in Programming
C++20 射影変換
faithandbrave
0
560
Porting a visionOS App to Android XR
akkeylab
0
230
#kanrk08 / 公開版 PicoRubyとマイコンでの自作トレーニング計測装置を用いたワークアウトの理想と現実
bash0c7
1
680
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
220
PostgreSQLのRow Level SecurityをPHPのORMで扱う Eloquent vs Doctrine #phpcon #track2
77web
2
490
A2A プロトコルを試してみる
azukiazusa1
2
1.3k
関数型まつりレポート for JuliaTokai #22
antimon2
0
160
ふつうの技術スタックでアート作品を作ってみる
akira888
0
390
エンジニア向け採用ピッチ資料
inusan
0
180
AIと”コードの評価関数”を共有する / Share the "code evaluation function" with AI
euglena1215
1
120
設計やレビューに悩んでいるPHPerに贈る、クリーンなオブジェクト設計の指針たち
panda_program
6
1.9k
Quand Symfony, ApiPlatform, OpenAI et LangChain s'allient pour exploiter vos PDF : de la théorie à la production…
ahmedbhs123
0
130
Featured
See All Featured
Making Projects Easy
brettharned
116
6.3k
GitHub's CSS Performance
jonrohan
1031
460k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.4k
The Straight Up "How To Draw Better" Workshop
denniskardys
234
140k
Bash Introduction
62gerente
614
210k
Build The Right Thing And Hit Your Dates
maggiecrowley
36
2.8k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
Java REST API Framework Comparison - PWX 2021
mraible
31
8.7k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.5k
Gamification - CAS2011
davidbonilla
81
5.3k
Designing for humans not robots
tammielis
253
25k
Transcript
A FRESH APPROACH TO DI TOOTHPICK https://github.com/stephanenicolas/toothpick/
ABOUT US Senior Android Dev @ Groupon ~20 years of
Java coding OSS: Dart, TP, BoundBox, … STEPHANE NICOLAS DANIEL MOLINERO REGUERA Android Dev @ Groupon Turbulence Ninja OSS: Dart, TP. +stephane nicolas @D_Lemures
5IF"OESPJE5FBNJT)JSJOH jobs.groupon.com/careers/
THE TALK WHY DI ? WHY TOOTHPICK? TOOTHPICK FEATURES
SOME EXAMPLES UNIT TESTING CONCLUSION SCOPE MODULES & BINDINGS SCOPE TREE SCOPE SINGLETONS MVP & STATE PRESERVATION MULTIPLE ACTIVITIES FLOWS #DroidConBos | @D_Lemures | @GrouponEng
WHY DI ? #DroidConBos | @D_Lemures
WHY DI ? DECOUPLE #DroidConBos | @D_Lemures
WHY DI ? DECOUPLE USES #DroidConBos | @D_Lemures
WHY DI ? DECOUPLE REUSE USES #DroidConBos | @D_Lemures
WHY DI ? DECOUPLE REUSE USES USES USES #DroidConBos |
@D_Lemures
WHY DI ? DECOUPLE REUSE TEST USES USES USES #DroidConBos
| @D_Lemures
WHY DI ? DECOUPLE REUSE TEST USES USES USES MOCK
USES #DroidConBos | @D_Lemures
WHY TOOTHPICK? #DroidConBos | @D_Lemures
WHY TOOTHPICK? SIMPLER #DroidConBos | @D_Lemures
WHY TOOTHPICK? SIMPLER BETTER TEST SUPPORT #DroidConBos | @D_Lemures
WHY TOOTHPICK? SIMPLER BETTER TEST SUPPORT EVEN FASTER #DroidConBos |
@D_Lemures
TOOTHPICK FEATURES public class SmoothieMachine { @Inject IceMachine iceMachine;
public void doSmoothie() { iceMachine.makeIce(); } } @Singleton public class IceMachine { Foo foo; @Inject public IceMachine(Foo foo) { this.foo = foo; } #DroidConBos | @D_Lemures
TOOTHPICK FEATURES public class SmoothieMachine { @Inject IceMachine iceMachine;
public void doSmoothie() { iceMachine.makeIce(); } } @Singleton public class IceMachine { Foo foo; @Inject public IceMachine(Foo foo) { this.foo = foo; } JSR 330 annotations→nothing new here #DroidConBos | @D_Lemures
TOOTHPICK FEATURES SCOPE SCOPE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES SCOPE SCOPE MAKE INJECTIONS #DroidConBos | @D_Lemures
TOOTHPICK FEATURES SCOPE SCOPE MAKE INJECTIONS public class MyApplication extends
Application { @Inject Machine machine; @Override protected void onCreate() { super.onCreate(); Scope appScope = Toothpick.openScope(this); appScope.installModules(…); Toothpick.inject(this, appScope); } } #DroidConBos | @D_Lemures
TOOTHPICK FEATURES SCOPE, MODULES & BINDINGS SCOPE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES SCOPE, MODULES & BINDINGS SCOPE BINDINGS #DroidConBos |
@D_Lemures
TOOTHPICK FEATURES SCOPE, MODULES & BINDINGS SCOPE BINDINGS MODULES #DroidConBos
| @D_Lemures
TOOTHPICK FEATURES SCOPE, MODULES & BINDINGS SCOPE BINDINGS MODULES public
class MyApplication extends Application { @Inject Machine machine; @Override protected void onCreate() { super.onCreate(); Scope appScope = Toothpick.openScope(this); appScope.installModules(new Module() {{ bind(Machine.class).to(IceMachine.class); }}); Toothpick.inject(this, appScope); } } #DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY 1 SCOPE SCOPE TREE #DroidConBos
| @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE SCOPE TREE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY 2 SCOPE SCOPE TREE #DroidConBos
| @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY 2 SCOPE SERVICE 1 SCOPE
SCOPE TREE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY 2 SCOPE SERVICE 1 SCOPE
FRAGMENT 1 SCOPE SCOPE TREE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY 2 SCOPE SERVICE 1 SCOPE
FRAGMENT 1 SCOPE FRAGMENT 2 SCOPE SCOPE TREE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY 2 SCOPE SERVICE 1 SCOPE
FRAGMENT 3 SCOPE FRAGMENT 1 SCOPE FRAGMENT 2 SCOPE SCOPE TREE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES public class LemonActivity extends Activity { @Inject Machine
machine; @Inject Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Scope scope = Toothpick.openScopes(getApplication(), this); scope.installModules(new Module() {{ bind(Context.class).toInstance(this); }}); Toothpick.inject(this, scope); } } SCOPE TREE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES public class LemonActivity extends Activity { @Inject Machine
machine; @Inject Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Scope scope = Toothpick.openScopes(getApplication(), this); scope.installModules(new Module() {{ bind(Context.class).toInstance(this); }}); Toothpick.inject(this, scope); } } SCOPE TREE APPLICATION SCOPE ACTIVITY SCOPE #DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY SCOPE SCOPE SINGLETONS #DroidConBos |
@D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY SCOPE APP SINGLETONS SCOPE SINGLETONS
#DroidConBos | @D_Lemures
TOOTHPICK FEATURES APPLICATION SCOPE ACTIVITY SCOPE APP SINGLETONS ACTIVITY SINGLETONS
SCOPE SINGLETONS #DroidConBos | @D_Lemures
TOOTHPICK FEATURES public class Module extends Module { public Module()
{ bind(Machine.class).toInstance(new Ice Machine()); } } SCOPE SINGLETONS SINGLETONS CAN BE DEFINED IN MODULES #DroidConBos | @D_Lemures
TOOTHPICK FEATURES @Singleton public class IceMachine { } @ActivitySingleton public
class SmoothieMachine { } APPLICATION SCOPE ACTIVITY SCOPE SCOPE SINGLETONS OR USING ANNOTATIONS #DroidConBos | @D_Lemures
SOME EXAMPLES MVP & STATE PRESERVATION #DroidConBos | @D_Lemures
APPLICATION SCOPE MVP & STATE PRESERVATION ACTIVITY SCOPE SOME EXAMPLES
#DroidConBos | @D_Lemures
APPLICATION SCOPE MVP & STATE PRESERVATION ACTIVITY SCOPE SOME EXAMPLES
#DroidConBos | @D_Lemures
APPLICATION SCOPE PRESENTER SCOPE MVP & STATE PRESERVATION ACTIVITY SCOPE
SOME EXAMPLES #DroidConBos | @D_Lemures
PRESENTER INSTANCE APPLICATION SCOPE PRESENTER SCOPE MVP & STATE PRESERVATION
ACTIVITY SCOPE SOME EXAMPLES #DroidConBos | @D_Lemures
PRESENTER INSTANCE APPLICATION SCOPE PRESENTER SCOPE MVP & STATE PRESERVATION
SOME EXAMPLES #DroidConBos | @D_Lemures
PRESENTER INSTANCE APPLICATION SCOPE PRESENTER SCOPE MVP & STATE PRESERVATION
ACTIVITY SCOPE SOME EXAMPLES #DroidConBos | @D_Lemures
MVP & STATE PRESERVATION public class MyActivity extends Activity {
@Inject MyPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Scope scope = openScopes(getApplication(), PresenterSingleton.class, this); Toothpick.inject(this, scope); } } SOME EXAMPLES #DroidConBos | @D_Lemures
@PresenterSingleton public class MyPresenter { String dealId; int quantity; }
PRESENTER SCOPE MVP & STATE PRESERVATION SOME EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS SOME
EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS Purchase
Flow SOME EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS Purchase
Flow SOME EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS SOME
EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS SOME
EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS SOME
EXAMPLES #DroidConBos | @D_Lemures
ACTIVITY 1 ACTIVITY 3 ACTIVITY 2 MULTI ACTIVITY FLOWS SOME
EXAMPLES #DroidConBos | @D_Lemures
APPLICATION SCOPE ACTIVITY 1 SCOPE FLOW SCOPE MULTI ACTIVITY FLOWS
SOME EXAMPLES #DroidConBos | @D_Lemures
APPLICATION SCOPE ACTIVITY 1 SCOPE FLOW SCOPE MULTI ACTIVITY FLOWS
SOME EXAMPLES #DroidConBos | @D_Lemures
APPLICATION SCOPE ACTIVITY 1 SCOPE FLOW SCOPE ACTIVITY 2 SCOPE
MULTI ACTIVITY FLOWS SOME EXAMPLES #DroidConBos | @D_Lemures
APPLICATION SCOPE ACTIVITY 1 SCOPE FLOW SCOPE ACTIVITY 3 SCOPE
ACTIVITY 2 SCOPE MULTI ACTIVITY FLOWS SOME EXAMPLES #DroidConBos | @D_Lemures
APPLICATION SCOPE FLOW SCOPE MULTI ACTIVITY FLOWS SOME EXAMPLES #DroidConBos
| @D_Lemures
APPLICATION SCOPE MULTI ACTIVITY FLOWS SOME EXAMPLES #DroidConBos | @D_Lemures
MVP & STATE PRESERVATION public class MyActivity extends Activity {
@Inject ShoppingCart shoppingCart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Scope scope = openScopes(getApplication(), FlowSingleton.class, this); Toothpick.inject(this, scope); } } SOME EXAMPLES #DroidConBos | @D_Lemures
@FlowSingleton public class ShoppingCart { List<PurchaseItem> purchases… } FLOW SCOPE
MULTI ACTIVITY FLOWS SOME EXAMPLES #DroidConBos | @D_Lemures
UNIT TESTING WE TEST UNITS #DroidConBos | @D_Lemures
UNIT TESTING WE TEST UNITS MOCK USES WE MOCK DEPENDENCIES
#DroidConBos | @D_Lemures
UNIT TESTING public class SmoothieMachine { @Inject IceMachine iceMachine; @Inject
SyrupDispenser syrupDispenser; public void doSmoothie() { Smoothie smoothie = iceMachine.makeIce(); syrupDispenser.addSyrup(smoothie); return smoothie; } } WE WANT TO SIMULATE THE DEPENDENCIES #DroidConBos | @D_Lemures
UNIT TESTING public class TestSmoothieMachine extends EasyMockSupport { @Rule public
EasyMockRule easyMockRule = new EasyMockRule(this); @Mock IceMachine iceMachineMock; @Mock SyrupDispenser syrupDispenserMock; @Mock Smoothie smoothieMock; @Test public void doSmoothie_should_createSmoothie() { // GIVEN expect(iceMachineMock.makeIce()).andReturn(smoothieMock); syrupDispenserMock.addSyrup(smoothieMock); replayAll(); // WHEN Smoothie smoothie = smoothieMachine.doSmoothie(); // THEN assertThat(smoothie, sameInstance(smoothieMock)); verifyAll(); } } 1. CREATE MOCKS -> EASYMOCK #DroidConBos | @D_Lemures
UNIT TESTING public class TestSmoothieMachine extends EasyMockSupport { @Rule public
EasyMockRule easyMockRule = new EasyMockRule(this); @Rule public ToothPickRule toothPickRule = new ToothPickRule(this, “testScope”); @Mock IceMachine iceMachineMock; @Mock SyrupDispenser syrupDispenserMock; @Mock Smoothie smoothieMock; @Inject SmoothieMachine classUnderTest; @Test public void doSmoothie_should_createSmoothie() { // GIVEN expect(iceMachineMock.makeIce()).andReturn(smoothieMock); syrupDispenserMock.addSyrup(smoothieMock); replayAll(); // WHEN toothPickRule.inject(this); Smoothie smoothie = smoothieMachine.doSmoothie(); // THEN assertThat(smoothie, sameInstance(smoothieMock)); verifyAll(); } } 2. INJECT MOCKS -> TOOTHPICK #DroidConBos | @D_Lemures
CONCLUSION QUESTIONS ? COMMENTS ? #DroidConBos | @D_Lemures | @GrouponEng
CONCLUSION QUESTIONS ? COMMENTS ? #DroidConBos | @D_Lemures | @GrouponEng
A FRESH APPROACH TO DI TOOTHPICK https://github.com/stephanenicolas/toothpick/ +stephane nicolas @D_Lemures