Slide 1

Slide 1 text

-*/&גࣜձࣾ-*/&ίϛϡχέʔγϣϯϓϥοτϑΥʔϜ։ൃࣨେੴক๜ -*/&"OESPJEΞϓϦͷج൫Λࢧ͑Δ 044ϥΠϒϥϦ-JDI

Slide 2

Slide 2 text

"CPVUNF w -*/&ίϛϡχέʔγϣϯϓϥοτϑΥʔϜ։ൃࣨॴଐ w -*/&ΞϓϦͷج൫෦෼ͷ։ൃΛ୲౰ w -*/&%&7%":ʹ΋ొஃ w ݸਓϒϩάͰ͸࠷ۙ"QQMF.ͷ࿩͕όζͬͨ

Slide 3

Slide 3 text

-*/&ΞϓϦͷ՝୊ w ೥͍ۙྺ࢙͕͋Γɺ͍ΘΏΔʮٕज़తෛ࠴ʯ͕ଟ͍ w ίʔυͷෳࡶ౓͕ߴ͘ɺमਖ਼΍৽ػೳ௥Ճʹ͔͔Δίετ͕େ͖͍ w Ϗϧυʹ͕͔͔࣌ؒΔ w 41%:ϓϩτίϧͷ࠾༻ͳͲͷಠࣗͷ࡞ΓࠐΈ͕ɺ࠷ۙͷ։ൃ؀ڥͷมԽ "OESPJE04΍J04ͷΞοϓσʔτɺ։ൃݴޠ΍ϥΠϒϥϦͷมԽͳͲ ʹ ରԠͰ͖͍ͯͳ͍

Slide 4

Slide 4 text

-*/5ϓϩδΣΫτͷ্ཱͪ͛ w -*/5 -*/&*NQSPWFNFOUGPS/FYU5FOZFBST w -*/&ΞϓϦͷج൫Λվળ͢ΔͨΊɺΫϥΠΞϯτଆɾαʔόʔଆ૒ํ͕ ڠྗͯ͠ࠓޙ೥Λݟਾ͑ͨվળΛߦ͏ w ओͱͯ͠ωοτϫʔΫϓϩτίϧ΍σʔλಉظ·ΘΓͷվળ w ৄࡉ͸-*/&%&7%":ͷηογϣϯʹͯ w IUUQTMJOFEFWEBZMJOFDPSQDPNKQTFTTJPOT"

Slide 5

Slide 5 text

-*/5ϓϩδΣΫτͷ੒Ռͷ044Խ w -*/5ϓϩδΣΫτͷ੒Ռ͸-*/&ΞϓϦҎ֎ʹ΋ల։͍͖͍ͯͨ͠ w -JCSBSZNPEVMFͱͯ͠ଞͷΞϓϦ΍4%,͔Β΋࢖༻͠΍͘͢͢Δ w ൚༻తͳػೳ͸044ͱͯࣾ͠֎ʹ΋ެ։͢Δ w ֎෦͔ΒͷϑΟʔυόοΫ͕ड͚ΒΕΕ͹࣭ΛΑΓߴΊΒΕΔ w -JDIIUUQTHJUIVCDPNMJOFMJDI

Slide 6

Slide 6 text

-JDI w "OESPJEΞϓϦ޲͚ͷMJCSBSZDPMMFDUJPO w ݱ࣌఺Ͱ͸lDPNQPOFOUz lWJFXNPEFMz lMJGFDZDMFz lPLIUUQz lUISJGUzͷ ͭͷϥΠϒϥϦ͕͋Δ w ͦΕͧΕͷϥΠϒϥϦ͸ಠཱ͍ͯ͠ΔͷͰඞཁͳ΋ͷ͚ͩར༻Մೳ w ຊ೔͸l-JDIDPNQPOFOUzʹ͍ͭͯ঺հ IUUQTHJUIVCDPNMJOFMJDI

Slide 7

Slide 7 text

-JDI$PNQPOFOU w 4JOHMFUPOΦϒδΣΫτͷ؅ཧΛ͢ΔͨΊͷϥΠϒϥϦ w %BHHFS ,PJOͱ͍ͬͨ%*πʔϧͷ୅ΘΓͱͳΔ΋ͷ w طଘͷ%*πʔϧΛஔ͖׵͑ͣʹิ׬తʹར༻͢Δ͜ͱ΋ग़དྷΔ

Slide 8

Slide 8 text

-JDI$PNQPOFOUͷಛ௃ w ࢖༻͢ΔͨΊʹ֮͑Δ͜ͱ͕গͳ͍ w (MPCBMͳঢ়ଶΛ࣋ͨͣɺ"QQMJDBUJPOPO$SFBUF ͳͲͰͷॳظԽ͕ෆཁ w MB[Z͕,PUMJOͷEFMFHBUFEQSPQFSUZͱͯ͠ॻ͚Δ w JOUFSGBDFͱ࣮૷Λ؆୯ʹ෼཭Ͱ͖Δ w -JCSBSZNPEVMF΍%ZOBNJDGFBUVSFNPEVMFͰ΋໰୊ͳ͘ಈ͘ w #VJMEUZQF΍qBWPSʹΑΔ࣮૷ͷ੾Γସ͕͑؆୯ʹͰ͖Δ w 6OJUUFTUͰϞοΫΦϒδΣΫτʹࠩ͠ସ͑Δͷ΋؆୯ w ίʔυੜ੒Λ͠ͳ͍ͷͰϏϧυ͕࣌ؒԆͼͳ͍

Slide 9

Slide 9 text

جຊతͳ࢖͍ํ w $PNQPOFOUΛఆٛ͢Δ class FooComponent { // snip... companion object : ComponentFactory() { override fun createComponent(context: Context): FooComponent = FooComponent() } }

Slide 10

Slide 10 text

جຊతͳ࢖͍ํ w 'PP$PNQPOFOUͷΠϯελϯεΛऔಘ w 'PP$PNQPOFOUͷΠϯελϯεΛMB[Zʹऔಘ w 'SBHNFOUͰͷ࢖༻ྫ val fooComponent = context.getComponent(FooComponent) val fooComponent by context.component(FooComponent) class FooFragment : Fragment() { private val fooComponent by component(FooComponent) // snip... }

Slide 11

Slide 11 text

JOUFSGBDFͱ࣮૷ͷ෼཭ w ࢖͏ଆ͔Β͸'PP$PNQPOFOUΠϯλʔϑΣʔε͚͕ͩݟ͑Ε͹Α͍ w 'PP$PNQPOFOU*NQM͸೚ҙͷϞδϡʔϧʹஔ͚Δ interface FooComponent { // snip... companion object : ComponentFactory() { override fun createComponent(context: Context): FooComponent = delegateToServiceLoader(context) } } @AutoService(FooComponent::class) class FooComponentImpl : FooComponent { // snip... }

Slide 12

Slide 12 text

ෳ਺ͷ࣮૷ΫϥεΛ੾Γସ͑Δ EFCVHϏϧυͰ͸%FCVH'PP$PNQPOFOU*NQM ͦΕҎ֎Ͱ͸'PP$PNQPOFOU*NQM͕༻͍ΒΕΔ // path: src/debug/java/DebugFooComponentImpl.kt @AutoService(FooComponent::class) class DebugFooComponentImpl : FooComponent, ServiceLoaderComponent { override val loadPriority: Int get() = 10 // snip... } // path: src/main/java/FooComponentImpl.kt @AutoService(FooComponent::class) class FooComponentImpl : FooComponent, ServiceLoaderComponent { override val loadPriority: Int get() = 0 // snip... }

Slide 13

Slide 13 text

࣮ߦ࣌ͷίετʹ͍ͭͯ w JOUFSGBDFͱ࣮૷Λ෼཭͢Δػೳ͸+BWBͷ4FSWJDF-PBEFSʹΑ࣮ͬͯݱ w 4FSWJDF-PBEFS͸಺෦ͰϦϑϨΫγϣϯΛ࢖༻ w ϦϦʔεϏϧυͰ͸ɺ3ͷ࠷దԽʹΑΓ4FSWJDF-PBEFSͷݺͼग़͕͠ ΠϯϥΠϯԽ͞ΕΔ w ϦϑϨΫγϣϯͷίʔυ͕আڈ͞ΕɺΦʔόʔϔουθϩʂ w ͜ͷ࢓૊Έ͸%ZOBNJDGFBUVSFNPEVMFͰ΋໰୊ͳ͘ಈ࡞͢Δ

Slide 14

Slide 14 text

6OJUUFTUͷॻ͖ํ 'PP6TF$BTFͷGPP3FQPTJUPSZΛϞοΫͯ͠ςετ͢Δʹ͸࣍ͷΑ͏ʹॻ͘ class FooRepository(context: Context) { suspend fun findFoo(key: String): Foo { /* TODO */ } companion object : ComponentFactory() { override fun createComponent(context: Context): FooRepository = FooRepository(context) } } class FooUseCase(context: Context) { private val fooRepository by context.component(FooRepository) // snip… }

Slide 15

Slide 15 text

6OJUUFTUͷॻ͖ํ @RunWith(AndroidJUnit4::class) class FooUseCaseTest { @Test fun testFooUseCase() { val expectedValue = Foo() // Set a mock of FooRepository. mockComponent(FooRepository) { onBlocking { findFoo(any()) } doReturn expectedValue } val context = ApplicationProvider.getApplicationContext() val fooUseCase = FooUseCase(context) // TODO: Write test cases for fooUseCase. } }

Slide 16

Slide 16 text

-JDI$PNQPOFOUΛಋೖͨ͠ޮՌ w MB[Z͕؆୯ʹॻ͚ΔͷͰɺىಈ࣌ͷίετΛ࡟ݮ͠΍͘͢ͳͬͨ w ϚϧνϞδϡʔϧؒͷґଘؔ܎ղܾ͕ͱͯ΋؆୯ʹͰ͖ΔΑ͏ʹͳͬͨ w ڊେͳϞϊϦγοΫϓϩδΣΫτͩͬͨ-*/&ΞϓϦ͕ػೳ͝ͱʹ෼ׂ͞Ε ։ൃޮ཰͕Ξοϓͨ͠ w %ZOBNJDGFBUVSFNPEVMFʹΑΓΞϓϦͷ༰ྔΛ࡟ݮͰ͖ΔΑ͏ʹͳͬͨ

Slide 17

Slide 17 text

'"2 w 4JOHMFUPOҎ֎ͷΦϒδΣΫτ͸ѻ͑ͳ͍ͷ w 7JFX.PEFMͰ͋Ε͹-JDI7JFX.PEFM͕࢖͑Δ w -JDI$PNQPOFOUͱಉ༷ʹ࢖͑Δ΄͔ɺ4BWFE4UBUFΛEFMFHBUFE QSPQFSUJFTͱͯ͠ૢ࡞͢Δ͜ͱ΋Ͱ͖Δ w "DUJWJUZTDPQFE΍'SBHNFOUTDPQFEͳΦϒδΣΫτ͸Ϟμϯͳ "OESPJEΞϓϦͰ͸ෆཁͳ͸ͣ w ϏδωεϩδοΫ͸7JFX.PEFMҎԼͷ૚ʹ࣮૷͠ɺ"DUJWJUZ΍ 'SBHNFOU͸7JFX.PEFMͱ7JFXͷCJOEJOH͚ͩΛߦ͏΂͖

Slide 18

Slide 18 text

ଞͷ%*πʔϧͱͷ࿈ܞ w ͱ͸͍͑ɺଞͷ%*πʔϧʹ׳Εͨਓʹ͸෺଍Γͳ͍఺΋͋ΔͩΖ͏ w -JDI$PNQPOFOUΛଞͷ%*πʔϧͱ૊Έ߹Θͤͯ࢖͏ͷ΋ྑ͍ w Ϟδϡʔϧؒͷґଘؔ܎ղܾ͚ͩʹ-JDI$PNQPOFOUΛ࢖͏ͳͲ w %BHHFSͱ૊Έ߹Θͤͨྫ @Module object FooModule { @Provides fun provideFooComponent(application: Application): FooComponent = application.getComponent(FooComponent) }

Slide 19

Slide 19 text

·ͱΊ w -JDI͸-*/&ΞϓϦͷվળϓϩδΣΫτͷதͰੜ·Εͨ044ϥΠϒϥϦ w IUUQTHJUIVCDPNMJOFMJDI w -JDI$PNQPOFOU͸ΞϓϦͷϚϧνϞδϡʔϧԽΛࢧԉ͢ΔͨΊʹ࡞ΒΕͨ %*πʔϧ w ܰྔ͔ͭߴ଎Ͱ͋Δ఺΋ΞϐʔϧϙΠϯτ w %BHHFSͳͲͷଞͷ%*πʔϧͱ૊Έ߹Θͤͯ࢖͏ͷ΋ྑ͍ w -JDIʹ͸7JFX.PEFM΍0L)UUQͷར༻Λࢧԉ͢ΔͨΊͷϥΠϒϥϦ΋͋Δ

Slide 20

Slide 20 text

5IBOLZPV