Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DX Improvements

DX Improvements

Explains how we, as an engineering team, are trying to improve our DX (Developer Experience) and push things forward while keeping it up.

Keishin Yokomaku

September 12, 2019
Tweet

More Decks by Keishin Yokomaku

Other Decks in Technology

Transcript

  1. DX Improvements Why DX matters? ▸ ϓϩμΫτ͸೔ʑ੒௕Λଓ͚Δ ▸ ৽ػೳͷ௥Ճ ▸

    طଘػೳͷվम ▸ όάमਖ਼ ▸ ͳͲ merpay Android Engineers meetup 3
  2. DX Improvements Why DX matters? ▸ ιʔείʔυ΋ຖ೔มԽΛ͠ଓ͚Δ ▸ ৽͍͠Ϋϥεɾϝιουͷ௥Ճ ▸

    طଘΫϥεɾϝιουͷৼΔ෣͍ͷมߋ ▸ Ϣχοτςετͷ௥Ճɾߋ৽ ▸ ͳͲ merpay Android Engineers meetup 4
  3. DX Improvements Why DX matters? ▸ ୹ظؒͷΠςϨʔγϣϯΛܧଓ͠ɺϓϩμΫτΛ੒௕ͤ͞Δϓϩηε ▸ ΞδϟΠϧ ▸

    1 ~ 2 िؒͷεϓϦϯτ ▸ ࡉ͔͘ϓϥϯχϯά͠ɺࡉ͔͘੒Ռ෺ΛੵΈ্͍͛ͯ͘ merpay Android Engineers meetup X
  4. DX Improvements Why DX matters? ▸ มԽ΁ͷదԠ͕ٻΊΒΕଓ͚Δ ▸ ૉૣ͍ػೳ࣮૷ʢࡉ͔͘࡞Γ্͍͛ͯ͘ϓϩηεͷ܁Γฦ͠ʣ ▸

    ૉૣ͍ৼΓฦΓʢࡉֶ͔͘ͼΛൃݟ͠దԠ͍ͯ͘͠ϓϩηεͷ܁Γฦ͠ʣ ▸ ͜ΕΒ͕͏·͘Ͱ͖͍ͯΔ͔Ͳ͏͔Ͱ DX ͕ܾ·Δ merpay Android Engineers meetup 5
  5. DX Improvements Good DX ▸ ૉૣ͍ػೳ࣮૷Λ࣮ݱ͢Δ͜ͱ͕Β ▸ มߋʹͭΑ͍ઃܭ΍ςετͷ࢓૊Έ ▸ ໨తʹ͔ͳͬͨϑϨʔϜϫʔΫͷར༻

    ▸ ݟੵ΋ΓͷͨΊͷυϝΠϯ஌ࣝ ▸ ݟੵ΋ΓͷͨΊͷٕज़త஌ݟɾܦݧ ▸ ͳͲ merpay Android Engineers meetup 6
  6. DX Improvements Bad DX ▸ ૉૣ͍ػೳ࣮૷Λ્֐͢Δ͜ͱ͕Β ▸ ৽ػೳ͕ଞͷطଘػೳʹӨڹΛ༩͑Δ ▸ όάमਖ਼͕ผͷόάΛݺͿ

    ▸ ςετ͕ॻ͖ͮΒ͍ɾॻ͍͍ͯͳ͍ ▸ ଞͷมߋࠩ෼ͱͷίϯϑϦΫτ͕ଟ͍ ▸ ͳͲ merpay Android Engineers meetup 8
  7. DX Improvements Bad DX ▸ ૉૣ͍ৼΓฦΓΛ્֐͢Δ͜ͱ͕Β ▸ ৼΓฦΒͳ͍ ▸ ௿͍৺ཧత҆શੑ

    ▸ ՝୊ײ͕ڞ༗Ͱ͖ͳ͍ɺվળఏҊΛ͠ͳ͍ɺͳͲ ▸ ղܾࡦ͕͏·͘ػೳ͔ͨ͠ܭଌ͠ͳ͍ ▸ ͳͲ merpay Android Engineers meetup 9
  8. DX Improvements Why DX matters? ▸ ѱ͍ DX ͸ϓϩμΫτͷܧଓతͳ੒௕Λ๦͛ͯ͠·͏ ▸

    ਎ಈ͖͕औΓͮΒ͘ͳΓٻΊΒΕΔεϐʔυͰ։ൃ͕͢͢·ͳ͘ͳΔ ▸ DX ͸์͓ͬͯ͘ͱѱ͘ͳΔ ▸ ׂΕ૭ཧ࿦ ▸ ୭Ͱ΋ׂΕ૭͸࡞ͬͯ͠·͏΋ͷ ▸ ͕࣌ؒͨͭͱউखʹ૭ׂ͕ΕΔ͜ͱ΋͋Δ merpay Android Engineers meetup 10
  9. DX Improvements DX (Developer Experience) Improvements in Merpay Android ▸

    ϝϧϖΠ Android νʔϜͰ࣮ࢪͨ͠ DX վળͷΞΫγϣϯ 1. ݱঢ়෼ੳ 2. վળఏҊ 3. ࣮ߦ merpay Android Engineers meetup 14
  10. DX Improvements Analyze: ݱঢ়෼ੳ ▸ KPT ▸ ͏·͘Ͱ͖͍ͯΔͱࢥ͍ͬͯΔ͜ͱ ▸ վળ͍ͨ͠ͱࢥ͍ͬͯΔ͜ͱ

    ▸ վળͷ༏ઌॱҐ෇͚ ▸ ՝୊ʹର͢Δશһͷ໨ઢΛ߹ΘͤΔͨΊͷଧͪख merpay Android Engineers meetup 16
  11. DX Improvements Analyze: ݱঢ়෼ੳ ▸ ͏·͘Ͱ͖͍ͯΔͱࢥ͍ͬͯΔ͜ͱ ▸ ϚϧνϞδϡʔϧͰ Feature ͝ͱʹ෼཭ͨ݁͠Ռɺେਓ਺Ͱ΋ίϯϑϦΫτ͕

    গͳ͘։ൃΛਐΊΒΕ͍ͯΔ ▸ Redux Ͱঢ়ଶͷભҠͷݟ௨ཱ͕ͯ͠ΒΕ͍ͯΔɺςετ͕ॻ͖΍͍͢ ▸ σʔλϨΠϠʔ͕੔උ͞Ε͍ͯͯ୯७ʹཧղͰ͖Δ ▸ ͳͲ… merpay Android Engineers meetup 17
  12. DX Improvements Analyze: ݱঢ়෼ੳ ▸ վળ͍ͨ͠ͱࢥ͍ͬͯΔ͜ͱ ▸ ςετΧόϨοδ͕௿͍ɻಛʹ View ϨΠϠʔͷςετ͕ॻ͚͍ͯͳ͍ɻ

    ▸ ෳࡶͰϒϥοΫϘοΫεͳφϏήʔγϣϯϑϨʔϜϫʔΫͷཧղ͕େมɻ ▸ Ϟδϡʔϧ͝ͱʹॻ͖ํͷ౷Ұײ͕ͳ͍͜ͱ͕͋Δɻ ▸ CI ʹ͕͔͔࣌ؒΓ͗ͯ͢͠·͍଴͕ͪൃੜ͍ͯ͠Δɻ ▸ ͳͲ… merpay Android Engineers meetup 18
  13. DX Improvements Analyze: ݱঢ়෼ੳ ▸ վળͷ༏ઌॱҐ෇͚: νʔϜ͕࠷΋ࠔ͍ͬͯͦ͏ͳ͜ͱ ▸ ςετΧόϨοδͷෆ଍ ▸

    ෳࡶͳφϏήʔγϣϯϑϨʔϜϫʔΫ ▸ ٕज़తͳཧ༝Ͱ଴ͪͷଟ͍։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ஌ࣝɾ஌ݟͷଐਓԽ merpay Android Engineers meetup 19
  14. DX Improvements Analyze: ݱঢ়෼ੳ ▸ վળͷ༏ઌॱҐ෇͚: νʔϜ͕࠷΋ࠔ͍ͬͯͦ͏ͳ͜ͱ ▸ ςετΧόϨοδͷෆ଍ ▸

    ෳࡶͳφϏήʔγϣϯϑϨʔϜϫʔΫ ▸ ٕज़తͳཧ༝Ͱ଴ͪͷଟ͍։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ஌ࣝɾ஌ݟͷଐਓԽ merpay Android Engineers meetup 20 ʹ ٕज़తෛ࠴
  15. DX Improvements Analyze: ݱঢ়෼ੳ ▸ վળͷ༏ઌॱҐ෇͚: νʔϜ͕࠷΋ࠔ͍ͬͯͦ͏ͳ͜ͱ ▸ ςετΧόϨοδͷෆ଍ ▸

    ෳࡶͳφϏήʔγϣϯϑϨʔϜϫʔΫ ▸ ٕज़తͳཧ༝Ͱ଴ͪͷଟ͍։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ஌ࣝɾ஌ݟͷଐਓԽ merpay Android Engineers meetup 21 ʹ DevOps
  16. DX Improvements Analyze: ݱঢ়෼ੳ ▸ վળͷ༏ઌॱҐ෇͚: νʔϜ͕࠷΋ࠔ͍ͬͯͦ͏ͳ͜ͱ ▸ ςετΧόϨοδͷෆ଍ ▸

    ෳࡶͳφϏήʔγϣϯϑϨʔϜϫʔΫ ▸ ٕज़తͳཧ༝Ͱ଴ͪͷଟ͍։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ஌ࣝɾ஌ݟͷଐਓԽ merpay Android Engineers meetup 22 ʹ ҉໧ͷ஌ࣝ
  17. DX Improvements Strategy Proposal: վળఏҊ ▸ ՝୊ྖҬ͝ͱʹऔΓ૊ΈΛϒϨΠΫμ΢ϯ͢Δ 1. ҉໧ͷ஌ࣝͷղফ ‣

    Be on the same page:
 νʔϜ͕҉໧తʹ͍࣋ͬͯΔ஌ࣝΛڞ༗͠ܗࣜԽ͢Δ࡞ઓ merpay Android Engineers meetup 26
  18. DX Improvements Strategy Proposal: վળఏҊ ▸ ՝୊ྖҬ͝ͱʹऔΓ૊ΈΛϒϨΠΫμ΢ϯ͢Δ 2. ٕज़తෛ࠴ͷղফ ‣

    Foundation Makeup:
 ςετΛॻ͖΍͘͢͢ΔͨΊͷ࢓૊ΈԽ΍ϘΠϥʔϓϨʔτͷղফͳͲ
 ػೳ։ൃΛࢧԉ͢ΔͨΊͷج൫Λͭ͘Δ࡞ઓ ‣ Foundation Refactoring:
 ෳࡶͳφϏήʔγϣϯΛ؆ૉԽ͢Δ࡞ઓ merpay Android Engineers meetup 27
  19. DX Improvements Strategy Proposal: վળఏҊ ▸ ՝୊ྖҬ͝ͱʹऔΓ૊ΈΛϒϨΠΫμ΢ϯ͢Δ 3. DevOps ͷվળ

    ‣ CI Campaign - Make the CI great again:
 ೔ʑͷ։ൃϫʔΫϑϩʔͷதͰগͳ͔Β͵࣌ؒΛ઎ΊΔ CI Λվળ͢Δ࡞ઓ ‣ United we code, United we ship:
 ϝϧϖΠͷػೳΛϝϧΧϦΞϓϦʹ౷߹͢ΔεςοϓΛվળ͢Δ࡞ઓ merpay Android Engineers meetup 28
  20. DX Improvements Milestone Proposal: վળఏҊ ▸ ͦΕͧΕͷऔΓ૊Έʹ͍ͭͯυΩϡϝϯτԽ͠ڞ༗ ▸ Background: औΓ૊Έʹࢸͬͨഎܠ͸ͳʹ͔

    ▸ Objective: Ͳ͏͍͏໨తͰऔΓ૊Ήͷ͔ ▸ Goal: ԿΛͲ͜·ͰऔΓ૊Ήͷ͔ ▸ Steps/Approaches: Ͳ͏΍ͬͯऔΓ૊Ήͷ͔ ▸ վળͷ໨త͔Βํ๏ʹࢸΔ·ͰɺνʔϜͰͷ໨ઢΛ͋ΘͤΔ merpay Android Engineers meetup 29
  21. DX Improvements Tacit Knowledge: ҉໧ͷ஌ࣝ ▸ νʔϜͱͯ͠ͷ՝୊ 1. ϑϨʔϜϫʔΫʹ͍ͭͯ஌͍ͬͯΔਓɾ͞ΘΕΔਓ͕ݶΒΕ͍ͯΔ 2.

    ਓʹΑͬͯࡉ͔͍࣮૷ํ๏΋·ͪ·ͪͳࣄ͕͋Δ ‣ ஌ࣝͷଐਓԽ͕ڧ͘ɺڞ༗͢΂͖஌͕ࣝڞ༗Ͱ͖͍ͯͳ͍ merpay Android Engineers meetup 32
  22. DX Improvements ࢀߟ࣮૷ (sample app) ͷϝϯςφϯε ▸ ϝϧϖΠ Android Ͱ࠾༻͍ͯ͠ΔΞʔΩςΫνϟͷࢀߟ࣮૷ΞϓϦ

    ▸ MVVM + Redux ͷ࣮૷ྫ͕͋ͬͨ ▸ Controller ΍ Navigation ͷ࣮૷ྫ͕ͳ͔ͬͨ: => ࡞Δ ▸ TODO ▸ ΑΓݱ࣮ʹଈ࣮ͨ͠૷ྫ: ωοτϫʔΫ I/O ͳͲ… ▸ KDoc ΍ Wiki ͸ʁ merpay Android Engineers meetup 34
  23. DX Improvements φϨοδγΣΞͷଅਐ ▸ ִि༵ۚͰϥϯν݉ษڧձΛ։࠵ ▸ ͜Ε·Ͱ7ճ։࠵ ▸ ऴྃ࣌ʹαʔϕΠΛ࣮ࢪ ▸

    ͲΜͳ͜ͱ͕஌ΕͯΑ͔͔ͬͨ ▸ ΋ͬͱ஌Γ͍ͨ͜ͱ͸ͲΜͳ͜ͱ͔ merpay Android Engineers meetup 35
  24. DX Improvements φϨοδγΣΞͷଅਐ ▸ ͜Ε·Ͱͷ಺༰ ▸ ؆ૉԽͨ͠φϏήʔγϣϯͷ࢓૊Έͷ঺հ ▸ Mockk ʹΑΔςετ

    ▸ View ϨΠϠͷߏ੒ͱϢχοτςετ ▸ ϩάऔಘͷޮՌతͳ࣮૷ྫ ▸ ͳͲ… merpay Android Engineers meetup 36
  25. DX Improvements Technical Debt: ٕज़తෛ࠴ ▸ ϝϧϖΠ Android ๊͕͍ٕ͑ͯͨज़తෛ࠴ 1.

    ݁߹౓ͷߴ͍ View ͱ௿͍ςετΧόϨοδ 2. ಠࣗφϏήʔγϣϯϑϨʔϜϫʔΫ merpay Android Engineers meetup 39
  26. DX Improvements Technical Debt: ٕज़తෛ࠴ ▸ ϝϧϖΠ Android ๊͕͍ٕ͑ͯͨज़తෛ࠴ 1.

    ݁߹౓ͷߴ͍ View ͱ௿͍ςετΧόϨοδ 2. ಠࣗφϏήʔγϣϯϑϨʔϜϫʔΫ merpay Android Engineers meetup 40
  27. ▸ MVVM + Redux DX Improvements ϝϧϖΠ Android ͷઃܭ merpay

    Android Engineers meetup 42 DataSource API Client Storage Model
  28. ▸ MVVM + Redux DX Improvements ϝϧϖΠ Android ͷઃܭ merpay

    Android Engineers meetup 43 DataSource API Client Storage ViewModel ViewModel Reducer
  29. ▸ MVVM + Redux DX Improvements ϝϧϖΠ Android ͷઃܭ merpay

    Android Engineers meetup 44 DataSource API Client Storage View ViewModel Reducer Controller
  30. DX Improvements ϝϧϖΠ Android ͷઃܭ: MVVM + Redux ▸ ͜ͷઃܭΛ࠾༻ͨ͠ཧ༝

    ▸ ෳࡶͳঢ়ଶ؅ཧΛ Redux ͷॿ͚ΛआΓͯݟ௨͠Α࣮͘૷͍ͨ͠ ▸ ঢ়ଶมԽΛؔ਺ͱͯ͠ఆٛ͠ɺϢχοτςετΛ؆୯ʹͰ͖ΔΑ͏ʹ͍ͨ͠ ▸ View ͷؔ৺Λঢ়ଶʹԠͨ͡ View ͷૢ࡞ͱঢ়ଶมԽͷτϦΨʔʹݶఆ͍ͨ͠ merpay Android Engineers meetup 45
  31. DX Improvements MVVM + Redux: ͏·͘Ͱ͖ͨ͜ͱ ▸ Model ͕ϨΠϠԽ͞Ε͍ͯΔ ▸

    ঢ়ଶΛද͢ΦϒδΣΫτΛఆٛͰ͖Δ ▸ ঢ়ଶભҠͷఆ͕ٛ Reducer ʹ·ͱΊΒΕΔ ▸ ঢ়ଶͷมԽΛ Reactive Extension ͰදݱͰ͖Δ ▸ View ͸ঢ়ଶΦϒδΣΫτͷมԽΛݕ஌ͯ͠ɺඞཁͳ View ͷૢ࡞ʹूத merpay Android Engineers meetup 46
  32. DX Improvements ViewModel example: ొ৔ਓ෺ ▸ Input: UI ͷΠϕϯτͱ ViewModel

    Ͱͷ Action ͷൃՐͷڮ౉͠໾ ▸ Store: Redux ͷ Storeɻঢ়ଶΛอ࣋͠มԽ͕͋ͬͨΒ௨஌͢Δ ▸ Reducer: Redux ͷ ReducerɻAction ʹԠͨ͡ঢ়ଶભҠΛఆٛ͢Δ ▸ ViewModel: Input ͔Β Action Λ࡞Γग़͠ Store ʹ఻ୡ͢Δ merpay Android Engineers meetup 47
  33. DX Improvements ViewModel ͷγʔέϯε: Action ΛൃՐ merpay Android Engineers meetup

    X View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action
  34. DX Improvements ViewModel ͷγʔέϯε: ঢ়ଶΛม͑Δ merpay Android Engineers meetup X

    View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action Recude Action
  35. DX Improvements ViewModel ͷγʔέϯε: ঢ়ଶΛอଘ merpay Android Engineers meetup X

    View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action Recude Action Change State
  36. DX Improvements ViewModel ͷγʔέϯε: ঢ়ଶมԽΛ௨஌ merpay Android Engineers meetup X

    View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action Recude Action Change State Notify state change
  37. DX Improvements ViewModel ͷγʔέϯε: API ͔ΒσʔλΛऔͬͯ͘Δ merpay Android Engineers meetup

    X View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action Recude Action Change State Notify state change Fetch data Data
  38. DX Improvements ViewModel ͷγʔέϯε: Action ΛൃՐ merpay Android Engineers meetup

    X View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action Recude Action Change State Notify state change Fetch data Data Dispatch loaded Action
  39. DX Improvements ViewModel ͷγʔέϯε: ঢ়ଶΛม͑ɺ௨஌͢Δ merpay Android Engineers meetup 48

    View ViewModel Model Reducer Store Trigger Input by click Dispatch loading Action Recude Action Change State Notify state change Fetch data Data Dispatch loaded Action Recude Action Change State Notify state change
  40. DX Improvements ViewModel example class SampleViewModel( private val input: SampleInput,

    private val sampleDataSource: SampleDataSource ) { private val store = Store(SampleState(), SampleReducer()) val state: Observable<SampleState> = store.states fun onCreate() { store.dispatch( input.loadData.flatMap { sampleDataSource.getData() .map(::FinishDataLoadingAction) .toObservable() .startWith(StartDataLoadingAction()) } ) } } 49 merpay Android Engineers meetup
  41. DX Improvements ViewModel example class SampleViewModel( private val input: SampleInput,

    private val sampleDataSource: SampleDataSource ) { private val store = Store(SampleState(), SampleReducer()) val state: Observable<SampleState> = store.states fun onCreate() { store.dispatch( input.loadData.flatMap { sampleDataSource.getData() .map(::FinishDataLoadingAction) .toObservable() .startWith(StartDataLoadingAction()) } ) } } X merpay Android Engineers meetup
  42. DX Improvements ViewModel example class SampleViewModel( private val input: SampleInput,

    private val sampleDataSource: SampleDataSource ) { private val store = Store(SampleState(), SampleReducer()) val state: Observable<SampleState> = store.states fun onCreate() { store.dispatch( input.loadData.flatMap { sampleDataSource.getData() .map(::FinishDataLoadingAction) .toObservable() .startWith(StartDataLoadingAction()) } ) } } X merpay Android Engineers meetup
  43. DX Improvements ViewModel example class SampleViewModel( private val input: SampleInput,

    private val sampleDataSource: SampleDataSource ) { private val store = Store(SampleState(), SampleReducer()) val state: Observable<SampleState> = store.states fun onCreate() { store.dispatch( input.loadData.flatMap { sampleDataSource.getData() .map(::FinishDataLoadingAction) .toObservable() .startWith(StartDataLoadingAction()) } ) } } 50 merpay Android Engineers meetup StartDataLoadingAction FinishDataLoadingAction
  44. DX Improvements Reducer example class SampleReducer : Reducer<SampleState, SampleAction> {

    overrider fun reduce( current: SampleState, action: SampleAction ): SampleState = when (action) { is StartDataLoadingAction -> { current.copy( data = Loading() ) } is FinishDataLoadingAction -> { current.copy( data = Success(action.data) ) } } } 51 merpay Android Engineers meetup
  45. DX Improvements MVVM + Redux: ͏·͘Ͱ͖ͨ͜ͱ ▸ Reducer ͷςετ ▸

    Action Λೖྗͨ͠Βɺద੾ͳঢ়ଶʹભҠ͢Δ ▸ ViewModel ͷςετ ▸ Input ͔Βద੾ͳ Action Λ (ෳ਺ճ) ൃՐ͢Δ merpay Android Engineers meetup 52
  46. DX Improvements ϝϧϖΠ Android ͷઃܭ: MVVM + Redux ▸ MVVM

    + Redux Ͱୡ੒Ͱ͖͍ͯΔ͜ͱ ✔ෳࡶͳঢ়ଶ؅ཧΛ Redux ͷॿ͚ΛआΓͯݟ௨͠Α࣮͘૷͍ͨ͠ ✔ঢ়ଶมԽΛؔ਺ͱͯ͠ఆٛ͠ɺϢχοτςετΛ؆୯ʹͰ͖ΔΑ͏ʹ͍ͨ͠ ‣ MVVM + Redux Ͱୡ੒Ͱ͖͍ͯͳ͍͜ͱ ? View ͷؔ৺Λঢ়ଶʹԠͨ͡ View ͷૢ࡞ͱঢ়ଶมԽͷτϦΨʔʹݶఆ͍ͨ͠ merpay Android Engineers meetup 53
  47. DX Improvements Conductor: View ϕʔεͷը໘ߏஙϥΠϒϥϦ ▸ Navigation Architecture Component ͕·ͩͳ͍ࠒ͔Β։ൃ͕࢝·ͬͨ

    ▸ Single Activity Ͱը໘ભҠΛ࣮ݱ͍ͨ͠ ▸ Fragment ΑΓ΋γϯϓϧʹը໘Λѻ͍͍ͨ ▸ Fragment in Fragment…? merpay Android Engineers meetup 54
  48. DX Improvements Conductor: View ϕʔεͷը໘ߏஙϥΠϒϥϦ ▸ Α͘࢖͏Ϋϥε ▸ Controller:
 Fragment

    ʹ૬౰͢ΔΫϥε ▸ Router:
 Navigation Architecture Component ͷ NavController ʹ૬౰͢ΔΫϥε merpay Android Engineers meetup 55
  49. DX Improvements Controller example class SampleController : Controller() { private

    val input = SampleInput() private val viewModel = SampleViewModel(input, SampleRepo()) override fun onAttach(view: View) { super.onAttach(view) button.setOnClickListener { input.loadData.input() } viewModel.state .subscribe { state -> when (state.data) { is Loading -> { progressBar.isVisible = true } is Success -> { progressBar.isVisible = false } is Failure -> { progressBar.isVisible = false } } }.addTo(compositeDisposable) } } 56 merpay Android Engineers meetup
  50. DX Improvements Controller example class SampleController : Controller() { private

    val input = SampleInput() private val viewModel = SampleViewModel(input, SampleRepo()) override fun onAttach(view: View) { super.onAttach(view) button.setOnClickListener { input.loadData.input() } viewModel.state .subscribe { state -> when (state.data) { is Loading -> { progressBar.isVisible = true } is Success -> { progressBar.isVisible = false } is Failure -> { progressBar.isVisible = false } } }.addTo(compositeDisposable) } } X merpay Android Engineers meetup
  51. DX Improvements Controller example class SampleController : Controller() { private

    val input = SampleInput() private val viewModel = SampleViewModel(input, SampleRepo()) override fun onAttach(view: View) { super.onAttach(view) button.setOnClickListener { input.loadData.input() } viewModel.state .subscribe { state -> when (state.data) { is Loading -> { progressBar.isVisible = true } is Success -> { progressBar.isVisible = false } is Failure -> { progressBar.isVisible = false } } }.addTo(compositeDisposable) } } X merpay Android Engineers meetup
  52. DX Improvements View ͱͯ͠ͷ Controller ▸ View ͱ ViewModel ͷڮ౉͠

    ▸ Input ʹΑΔ ViewModel ΁ͷೖྗ ▸ Input ͱ͍͏ܗͰந৅Խ͍ͯ͠ΔͷͰ୯७ ▸ State Λߪಡͯ͠ View Λૢ࡞ ▸ ϩδοΫΛϕλॻ͖͍ͯͯ͠ີ݁߹͍ͯ͠Δ merpay Android Engineers meetup 57
  53. DX Improvements ີ݁߹ͰςετΧόϨοδͷͳ͍ View ▸ State ͷߋ৽͔ΒͲͷΑ͏ʹ View Λૢ࡞͢Δ͔ςετͮ͠Β͍ ▸

    ViewModel ͷϞοΫ͕ͳ͍ͱ State ͕ྲྀͤͳ͍ ▸ Activity ͳͲͱಉ͘͡ Controller ΠϯελϯεΛૉ௚ʹ͸࡞Εͳ͍ ▸ ݁ՌςετΛॻ͔ͣʹखಈͰؤுͬͯ֬ೝ͍ͯͨ͠ merpay Android Engineers meetup 58
  54. DX Improvements ີ݁߹ͰςετΧόϨοδͷͳ͍ View ▸ View ͷ੹຿Λ͢΂ͯෛͬͨ Controller ▸ Controller

    ͸ Activity ΍ Fragment ͱಉ͡ Template Method Pattern ͷ࣮૷ ▸ ϥΠϑαΠΫϧ͝ͱద੾ͳॲཧΛ͢Δ৔ॴ ▸ ͋Γ͕ͪͳ Fat Activity ݱ৅ ▸ ద੾ͳ Delegate Λ࡞Γɺ
 Controller ͔Β͸ϥΠϑαΠΫϧ͝ͱద੾ͳϝιουݺͼग़͠ʹཹΊΔ merpay Android Engineers meetup 59
  55. DX Improvements ViewDelegate ▸ State ʹԠͨ͡ View ͷૢ࡞ʹ໊લΛ͚ͭΔ ▸ Controller

    ͔ΒʮState Λߪಡͯ͠ View Λૢ࡞ʯ͢Δ໾ׂΛҕৡ ▸ ςετ͔Β೚ҙͷ State Λ publish ͢Ε͹ɺ
 ରԠ͢Δ View ͷૢ࡞͕Ͱ͖͔ͨͲ͏͔ݕূͰ͖Δ ▸ Controller ͸ϥΠϑαΠΫϧʹैͬͨΦϒδΣΫτͷ؅ཧΛ͢Δ͚ͩ merpay Android Engineers meetup 60
  56. DX Improvements Controller example class SampleController : Controller() { private

    val input = SampleInput() private val viewModel = SampleViewModel(input, SampleRepo()) override fun onAttach(view: View) { super.onAttach() button.setOnClickListener { input.loadData.input() } viewModel.state .subscribe { state -> when (state.data) { is Loading -> { progressBar.isVisible = true } is Success -> { progressBar.isVisible = false } is Failure -> { progressBar.isVisible = false } } }.addTo(compositeDisposable) } } 61 merpay Android Engineers meetup
  57. DX Improvements ViewDelegate usage class SampleController : Controller() { private

    val input = SampleInput() private val viewModel = SampleViewModel(input, SampleRepo()) private lateinit var viewDelegate: SampleContract.ViewDelegate override fun onAttach(view: View) { super.onAttach(view) viewDelegate = SampleViewDelegate.of(view, input) viewDelegate.setupButtonClick() viewDelegate.subscribeState(viewModel.state).addTo(compositeDisposable) } } 62 merpay Android Engineers meetup
  58. DX Improvements ViewDelegate usage class SampleController : Controller() { private

    val input = SampleInput() private val viewModel = SampleViewModel(input, SampleRepo()) private lateinit var viewDelegate: SampleContract.ViewDelegate override fun onAttach(view: View) { super.onAttach(view) viewDelegate = SampleViewDelegate.of(view, input) viewDelegate.setupButtonClick() viewDelegate.subscribeState(viewModel.state)
 .addTo(compositeDisposable) } } 63 merpay Android Engineers meetup
  59. DX Improvements ViewDelegate implementation class SampleViewDelegate private constructor( override val

    button: Button, override val progressBar: ProgressBar, override val input: SampleInput ) : SampleContract.ViewDelegate { override fun subscribeState(states: Observable<SampleState>) = state.subscribe { state -> when (state.data) { is Loading -> { progressBar.isVisible = true } is Success -> { progressBar.isVisible = false } is Failure -> { progressBar.isVisible = false } } } 64 merpay Android Engineers meetup
  60. DX Improvements ϝϧϖΠ Android ͷઃܭ: MVVM + Redux ‣ ViewDelegate

    Λಋೖͯ͠ୡ੒Ͱ͖ͨ͜ͱ ✔View ͷؔ৺Λ"ঢ়ଶʹԠͨ͡ View ͷૢ࡞ͱঢ়ଶมԽͷτϦΨʔ”ʹݶఆ ✔Controller ͸ϥΠϑαΠΫϧ؅ཧʹूத ✔ViewDelegate ʹΑͬͯঢ়ଶʹԠͨ͡ View ͷૢ࡞ΛϢχοτςετՄೳʹ merpay Android Engineers meetup 65
  61. DX Improvements Technical Debt: ٕज़తෛ࠴ ▸ ϝϧϖΠ Android ๊͕͍ٕ͑ͯͨज़తෛ࠴ 1.

    ݁߹౓ͷߴ͍ View ͱ௿͍ςετΧόϨοδ 2. ಠࣗφϏήʔγϣϯϑϨʔϜϫʔΫ merpay Android Engineers meetup 66
  62. DX Improvements Multi-module ͰͷφϏήʔγϣϯ ▸ ଟ਺ͷ feature ϞδϡʔϧΛ΋ͭϚϧνϞδϡʔϧߏ੒ ▸ Feature

    A ͔Β Feature B ΁ͷφϏήʔγϣϯͷͨΊʹ࢓૊Έ͕ඞཁ ▸ ͢΂ͯͷ feature ϞδϡʔϧΛ஌͍ͬͯΔϞδϡʔϧͰφϏήʔγϣϯΛఆٛ merpay Android Engineers meetup 67
  63. DX Improvements Multi-module ͰͷφϏήʔγϣϯ merpay Android Engineers meetup 71 OriginalController

    DestinationController Feature B Feature A Navgigation OriginalNavigator
  64. DX Improvements Multi-module ͰͷφϏήʔγϣϯ ▸ ॳظͷಠࣗφϏήʔγϣϯϑϨʔϜϫʔΫ ▸ Conductor ͷφϏήʔγϣϯ෦෼Λϥοϓͨ͠΋ͷ ▸

    όοΫελοΫͳͲҰ෦ঢ়ଶΛಠࣗ؅ཧ͢Δ෦෼͕͋Δ ▸ ࣮૷ ▸ Controller ʹφϏήʔγϣϯ༻ͷϥϜμΛఆٛ ▸ ରԠ͢Δ Navigator ΫϥεͰϥϜμͷ࣮૷Λࢗ͢ merpay Android Engineers meetup 72
  65. DX Improvements Conductor ʹ͓͚ΔφϏήʔγϣϯͷ࢓૊Έ class OriginalController : Controller() { fun

    onButtonClick() { router.pushController( RouterTransaction.with(DestinationController()) ) } } 73 merpay Android Engineers meetup
  66. DX Improvements Conductor ʹ͓͚ΔφϏήʔγϣϯͷ࢓૊Έ class OriginalController : Controller() { fun

    onButtonClick() { router.pushController( RouterTransaction.with(DestinationController()) ) } } 74 merpay Android Engineers meetup ͜͜Λ͏·͘ந৅Խͭͭ͠ςετ͠΍͍͢ઃܭ͕ඞཁ
  67. DX Improvements Navigation ͷ࣮ྫ: վળલ class OriginalController : Controller {

    var navigateFromOkButton: (() -> Unit)? = null } class OriginalNavigator : Navigator { override fun startController() { controller?.run { navigateFromOkButton = { next(DestinationController()) } } } } 75 merpay Android Engineers meetup
  68. DX Improvements Navigation ͷ࣮ྫ: վળલ class OriginalController : Controller {

    var navigateFromOkButton: (() -> Unit)? = null } class OriginalNavigator : Navigator { override fun startController() { controller?.run { navigateFromOkButton = { next(DestinationController()) } } } } X merpay Android Engineers meetup
  69. DX Improvements Navigation ͷ࣮ྫ: վળલ class OriginalController : Controller {

    var navigateFromOkButton: (() -> Unit)? = null } class OriginalNavigator : Navigator { override fun startController() { controller?.run { navigateFromOkButton = { next(DestinationController()) } } } } X merpay Android Engineers meetup
  70. DX Improvements Needs improvement ▸ ΠϯλϑΣʔε͕ͳ͍ ▸ ϥϜμͰ֤ Controller ʹఆٛ͢Δ͔͠ͳ͍

    ▸ φϏήʔγϣϯͷϩδοΫΛϢχοτςετ͍͕ͨ͠…… ▸ ঢ়ଶΛಠࣗ؅ཧ͍ͯ͠Δ෦෼Λ͏·͘ϞοΫ͠ͳ͍ͱ͍͚ͳ͍ ▸ ϞοΫϥΠϒϥϦͷ spy ػೳ͕ͳ͍ͱݫ͍͠ merpay Android Engineers meetup 77
  71. DX Improvements How to improve ▸ φϏήʔγϣϯΛΠϯλϑΣʔεͱͯ͠ఆ͍ٛͨ͠ ▸ ΦϒδΣΫτͱͯ͠ৼΔ෣ͬͯ΄͍͠ ▸

    ঢ়ଶͷಠࣗ؅ཧΛ΍Ί͍ͨ ▸ Conductor ͕طʹ΍͍ͬͯΔ͜ͱΛࣗ෼͕ͨͪ΍Δඞཁ͸ͳ͍ ▸ ςετΛॻ͖΍͍ͨ͘͢͠ ▸ ্هͷ͜ͱ͕ୡ੒Ͱ͖ͨΒॻ͖΍͘͢ͳΔ͸ͣ merpay Android Engineers meetup 78
  72. DX Improvements Multi-module ͰͷφϏήʔγϣϯ merpay Android Engineers meetup 79 OriginalController

    DestinationController Feature B Feature A Navgigation OriginalNavigator OriginalNavigation
  73. DX Improvements Navigation ͷ࣮ྫ: վળޙ class OriginalController : Controller {

    val navigator: OriginalNavigation by lazy { /* … */ } } abstract class OriginalNavigation( controller: OriginalController ) : Navigation<OriginalController>(controller) { abstract fun navigateToDestination() } class OriginalNavigator( controller: OriginalController ) : OriginalNavigation(controller) { override fun navigateToDestination() { next(DestinationController()) } } 80 merpay Android Engineers meetup
  74. DX Improvements Navigation ͷ࣮ྫ: վળޙ class OriginalController : Controller {

    val navigator: OriginalNavigation by lazy { /* … */ } } abstract class OriginalNavigation( controller: OriginalController ) : Navigation<OriginalController>(controller) { abstract fun navigateToDestination() } class OriginalNavigator( controller: OriginalController ) : OriginalNavigation(controller) { override fun navigateToDestination() { next(DestinationController()) } } X merpay Android Engineers meetup
  75. DX Improvements Navigation ͷ࣮ྫ: վળޙ class OriginalController : Controller {

    val navigator: OriginalNavigation by lazy { /* … */ } } abstract class OriginalNavigation( controller: OriginalController ) : Navigation<OriginalController>(controller) { abstract fun navigateToDestination() } class OriginalNavigator( controller: OriginalController ) : OriginalNavigation(controller) { override fun navigateToDestination() { next(DestinationController()) } } X merpay Android Engineers meetup
  76. DX Improvements Navigation ͷ࣮ྫ: վળޙ class OriginalController : Controller {

    val navigator: OriginalNavigation by lazy { /* … */ } } abstract class OriginalNavigation( controller: OriginalController ) : Navigation<OriginalController>(controller) { abstract fun navigateToDestination() } class OriginalNavigator( controller: OriginalController ) : OriginalNavigation(controller) { override fun navigateToDestination() { next(DestinationController()) } } X merpay Android Engineers meetup
  77. DX Improvements Result: ੒Ռ ✔φϏήʔγϣϯΛΠϯλϑΣʔεͱͯ͠ఆ͍ٛͨ͠ ‣ ΠϯλϑΣʔε͕ఆٛͰ͖Δ࢓૊Έʹͳͬͨ ✔ঢ়ଶͷಠࣗ؅ཧΛ΍Ί͍ͨ ‣ Conductor

    ʹ೚͍ͤͯΔ ✔ςετΛॻ͖΍͍ͨ͘͢͠ ‣ φϏήʔγϣϯϩδοΫͷςετ͕ॻ͖΍͘͢ͳͬͨ merpay Android Engineers meetup 81
  78. DX Improvements Caveat: ςετΧόϨοδͷ਺ࣈͱ͏·͘෇͖߹͏ ‣ ViewDelegate ‣ State ʹԠͨ͡ View

    ͷૢ࡞Λݕূ͢Δ͜ͱʹҙຯ͕͋Δ ‣ Navigation ‣ ద੾ͳը໘ͷݺͼग़͠Λݕূ͢Δ͜ͱʹҙຯ͕͋Δ merpay Android Engineers meetup 84
  79. DX Improvements Development Process/Workflow: ։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ։ൃϓϩηεɾϫʔΫϑϩʔͷ՝୊ 1. ࣌ؒͷ͔͔Δ CI

    2. ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ 3. ࣌ؒͷ͔͔Δεςοϓ͕ෳ਺͋Δ౷߹खॱ ‣ ೔ʑͷ։ൃΠςϨʔγϣϯͷ଍͔ͤʹͳͬͯ͠·͏ཁҼΛղܾ͍ͯ͘͠ merpay Android Engineers meetup 86
  80. DX Improvements Development Process/Workflow: ։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ։ൃϓϩηεɾϫʔΫϑϩʔͷ՝୊ 1. ࣌ؒͷ͔͔Δ CI

    2. ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ 3. ࣌ؒͷ͔͔Δεςοϓ͕ෳ਺͋Δ౷߹खॱ ‣ ೔ʑͷ։ൃΠςϨʔγϣϯͷ଍͔ͤʹͳͬͯ͠·͏ཁҼΛղܾ͍ͯ͘͠ merpay Android Engineers meetup 87
  81. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ Ұճͷ git push Ͱಈ࡞͢Δ CI

    ͕ऴΘΔ·Ͱ ▸ ͍͍ͩͨ30෼ ▸ ͢΂ͯͷεςοϓΛஞ࣮࣍ߦ͍ͯͨ͠ ▸ Checkout → Environment Set up → Verify → Assemble → Save Cache merpay Android Engineers meetup 88
  82. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ ݸʑͷεςοϓͰ΋ඞཁҎ্ʹ͕͔͔͍࣌ؒͬͯͨ ▸ Ωϟογϡͷ෮ݩ: 4෼͘Β͍ ▸

    SDK ͷηοτΞοϓ: 1෼൒͘Β͍ ▸ Ϗϧυ: 6෼ऑ͘Β͍ ▸ ੒Ռ෺ͷอଘ: 4෼൒͘Β͍ ▸ Ωϟογϡͷอଘ: 8෼൒͘Β͍ merpay Android Engineers meetup 89
  83. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ εςοϓͷฒྻԽ ▸ Verify ͱ Assemble

    ͷಉ࣌ฒߦ ▸ ςετͷ࣮ߦํ๏ͷ޻෉ ▸ ෆඞཁͳॲཧͷ Spark Joy ▸ SDK ͷΞοϓσʔτ ▸ ڊେͳΩϟογϡͷอଘͱ෮ݩ merpay Android Engineers meetup 90
  84. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ Verify ͱ Assemble ͷಉ࣌ฒߦ ▸

    ͜Ε͚ͩͰ͔ͳΓૣ͘ CI ͕ճͤΔΑ͏ʹͳͬͨ merpay Android Engineers meetup 91
  85. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ ςετͷฒྻ࣮ߦ ▸ ςετΛॻ͖΍͍͢࡞Γʹͨ݁͠Ռɺ
 Ϣχοτςετͷςετέʔε͕രൃతʹ૿͑ͨ ▸

    Gradle ͷෳ਺ϓϩηεͰͷ࣮ߦͰ΋δϦශʹͳ͖ͬͯͨ ▸ CI ͷઃఆͰίϯςφΛෳ਺ىಈ͠ɺίϯςφ͝ͱʹҟͳΔςετΛಉ࣌ʹ࣮ߦ ▸ ref: https://tech.mercari.com/entry/2019/09/03/000000 merpay Android Engineers meetup 92
  86. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ ςετͷฒྻ࣮ߦ ▸ ςετΛॻ͖΍͍͢࡞Γʹͨ݁͠Ռɺ
 Ϣχοτςετͷςετέʔε͕രൃతʹ૿͑ͨ ▸

    Gradle ͷෳ਺ϓϩηεͰͷ࣮ߦͰ΋δϦශʹͳ͖ͬͯͨ ▸ CI ͷઃఆͰίϯςφΛෳ਺ىಈ͠ɺίϯςφ͝ͱʹҟͳΔςετΛಉ࣌ʹ࣮ߦ ▸ ref: https://tech.mercari.com/entry/2019/09/03/000000 merpay Android Engineers meetup 93
  87. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ ςετͷฒྻ࣮ߦͷઃఆ ▸ Gradle ͰϚϧνϞδϡʔϧߏ੒ͩͱɺCircleCI ͷ

    CLI πʔϧ͕࢖͍ͮΒ͍ ▸ ࣗ෼Ͱίϯςφ͝ͱʹͲͷςετΛ࣮ߦ͢Δ͔ܭࢉ͢Δ merpay Android Engineers meetup 96
  88. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ Ϗϧυ؀ڥͷίϯςφԽ ▸ Docker Λ࢖ͬͯ CI

    ▸ Ϗϧυʹඞཁͳ΋ͷ͸͢΂ͯΠϝʔδʹݻΊ͓ͯ͘ ▸ Android SDK ΛຖճΞοϓσʔτ͠ͳͯ͘΋Α͍ ▸ Πϝʔδͷόʔδϣϯ؅ཧ΋ՄೳʹͳΔ merpay Android Engineers meetup 98
  89. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ Ωϟογϡͷ؅ཧ ▸ Gradle ͕΋͍ͬͯΔΩϟογϡ͕ͱʹ͔͘େ͖͍ ▸

    Ωϟογϡ͢΂͖σΟϨΫτϦ͚ͩΩϟογϡ͢Δ ▸ ~/.gradle/caches ▸ ~/.gradle/wrapper merpay Android Engineers meetup 99
  90. DX Improvements ࣌ؒͷ͔͔Δ CI ▸ Ұճͷ git push Ͱಈ࡞͢Δ CI

    ͕ऴΘΔ·Ͱ ▸ ͍͍ͩͨ10෼ merpay Android Engineers meetup 100
  91. DX Improvements Development Process/Workflow: ։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ։ൃϓϩηεɾϫʔΫϑϩʔͷ՝୊ 1. ࣌ؒͷ͔͔Δ CI

    2. ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ 3. ࣌ؒͷ͔͔Δεςοϓ͕ෳ਺͋Δ౷߹खॱ ‣ ೔ʑͷ։ൃΠςϨʔγϣϯͷ଍͔ͤʹͳͬͯ͠·͏ཁҼΛղܾ͍ͯ͘͠ merpay Android Engineers meetup 101
  92. DX Improvements ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ ▸ Android Lint ΍ KtLint ͳͲ ▸

    CI Ͱಈ͔͍ͯ͠Δ͕ɺ݁Ռ͕ CI ͷϩάग़ྗʹ͔͠ग़ͳ͍ ▸ ຖճ CI ͷը໘Λ։͍ͯϩά͔ΒࢦఠΛ୳͠ग़͍ͯͨ͠ merpay Android Engineers meetup 102
  93. DX Improvements ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ ▸ GitHub ͷΠϯϥΠϯίϝϯτͰίʔυղੳͷࢦఠΛݟ͑ΔԽ͢Δ ▸ danger πʔϧͷಋೖͰղܾ ▸

    ݟ͑ΔԽͨ͠΋ͷ ▸ Android Lint ͱ KtLint ͷܯࠂ ▸ ࣦഊͨ͠Ϣχοτςετ ▸ apk ͷղੳ݁Ռ merpay Android Engineers meetup 103
  94. DX Improvements ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ ▸ ϚϧνϞδϡʔϧߏ੒ಛ༗ͷରԠ ▸ Ϟδϡʔϧ͝ͱʹࢄΒ͹ͬͨϨϙʔτϑΝΠϧͷऩू ▸ ࣗ෼Ͱ XML

    Λ͔͖ूΊͯɺͻͱͭʹ߹ମͯ͠ॻ͖ग़͢ ▸ ref: https://tech.mercari.com/entry/2019/09/03/000000 merpay Android Engineers meetup 104
  95. DX Improvements Development Process/Workflow: ։ൃϓϩηεɾϫʔΫϑϩʔ ▸ ։ൃϓϩηεɾϫʔΫϑϩʔͷ՝୊ 1. ࣌ؒͷ͔͔Δ CI

    2. ϑΟʔυόοΫ͕ݟͮΒ͍ίʔυղੳπʔϧ 3. ࣌ؒͷ͔͔Δεςοϓ͕ෳ਺͋Δ౷߹खॱ ‣ ೔ʑͷ։ൃΠςϨʔγϣϯͷ଍͔ͤʹͳͬͯ͠·͏ཁҼΛղܾ͍ͯ͘͠ merpay Android Engineers meetup 105
  96. DX Improvements ࣌ؒͷ͔͔Δεςοϓ͕ෳ਺͋Δ౷߹खॱ ▸ ϝϧϖΠ͸ϝϧΧϦΞϓϦͷػೳͷҰ෦ ▸ ϝϧϖΠͷػೳ͕ϝϧΧϦΞϓϦʹ౷߹͞ΕΔ·Ͱ 1. ϝϧϖΠϦϙδτϦͰػೳ։ൃ 2.

    λάΛଧͬͯ੒Ռ෺ (aar) ΛσϓϩΠ 3. ϝϧΧϦϦϙδτϦͰ੒Ռ෺ͷόʔδϣϯΛߋ৽ 4. ϝϧΧϦΞϓϦΛϏϧυ merpay Android Engineers meetup 106
  97. DX Improvements ࣌ؒͷ͔͔Δεςοϓ͕ෳ਺͋Δ౷߹खॱ ▸ ϝϧϖΠ͸ϝϧΧϦΞϓϦͷػೳͷҰ෦ ▸ ϝϧϖΠͷػೳ͕ϝϧΧϦΞϓϦʹ౷߹͞ΕΔ·Ͱ 1. ϝϧϖΠϦϙδτϦͰػೳ։ൃ 2.

    λάΛଧͬͯ੒Ռ෺ (aar) ΛσϓϩΠ 3. ϝϧΧϦϦϙδτϦͰ੒Ռ෺ͷόʔδϣϯΛߋ৽ 4. ϝϧΧϦΞϓϦΛϏϧυ merpay Android Engineers meetup 107
  98. DX Improvements Wrap up ▸ DX = Developer eXperience: ։ൃମݧ

    ▸ ೔ʑͷ։ൃ͕εϜʔζʹਐΊΒΕ͍ͯΔ͔Ͳ͏͔ ▸ Կ΋͠ͳͯ͘΋ DX ͸ѱ͘ͳΔ͜ͱ͕͋Δ ▸ νʔϜͱͯ͠ DX ͷվળʹܧଓతʹऔΓ૊Έଓ͚Δ͜ͱ ▸ ৺ཧత҆શੑ ▸ ໨ઢɾೝࣝ߹Θͤ merpay Android Engineers meetup 111