Slide 1

Slide 1 text

!ActivityΛվળͨ͠࿩ @lvla0805

Slide 2

Slide 2 text

MWMB MWMB Ѫᖒ๖ (Moyuru Aizawa) - Lead Kotlin engineer of Pairs Div. Eureka, Inc.

Slide 3

Slide 3 text

- Pairs - Couples - a member of IAC/Match Group

Slide 4

Slide 4 text

Pairs

Slide 5

Slide 5 text

Pairs

Slide 6

Slide 6 text

·ͣ͸ཧ૝ͷ͓૬खΛ୳͠·͢

Slide 7

Slide 7 text

ؾʹͳΔ͓૬खʹ͍͍Ͷ!ΛૹΔ

Slide 8

Slide 8 text

Ϛονϯάޙɺϝοηʔδަ׵

Slide 9

Slide 9 text

αϯϓϧίʔυʹؔͯ͠

Slide 10

Slide 10 text

Pairs͸Java/Kotlin͕ࠞࡏ͍ͯ͠·͢ɻ Αͬͯɺαϯϓϧίʔυʹ͓͍ͯ΋྆ ݴޠ͕ར༻͞Ε͍ͯ·͢ɻ

Slide 11

Slide 11 text

Kotlin͕ۤखͳϑϨϯζ ͷΈͳ͞Μ

Slide 12

Slide 12 text

ͱ͠ΐ͔ΜͰKotlinʹ͍ͭ ͯ͠Β΂·͠ΐʔ!

Slide 13

Slide 13 text

Instanceੜ੒ final Serval serval = new Serval(); Kaban kaban = new Kaban(); val serval = Serval() var kaban = Kaban()

Slide 14

Slide 14 text

Instanceੜ੒ final Serval serval = new Serval(); Kaban kaban = new Kaban(); val serval = Serval() var kaban = Kaban()

Slide 15

Slide 15 text

Instanceੜ੒ final Serval serval = new Serval(); Kaban kaban = new Kaban(); val serval = Serval() var kaban = Kaban()

Slide 16

Slide 16 text

Instanceੜ੒ final Serval serval = new Serval(); Kaban kaban = new Kaban(); val serval = Serval() var kaban = Kaban()

Slide 17

Slide 17 text

Class public class JapariBus { private final Trailer trailer; private final Container container; public JapariBus(Trailer trailer, Container container) { this.trailer = trailer; this.container = container; } } class JapariBus(private val trailer: Trailer, private val container: Container) Έ͔͡ʔ͍

Slide 18

Slide 18 text

Class public class JapariBus { private final Trailer trailer; private final Container container; public JapariBus(Trailer trailer, Container container) { this.trailer = trailer; this.container = container; } } class JapariBus(private val trailer: Trailer, private val container: Container) Έ͔͡ʔ͍

Slide 19

Slide 19 text

Class public class JapariBus { private final Trailer trailer; private final Container container; public JapariBus(Trailer trailer, Container container) { this.trailer = trailer; this.container = container; } } class JapariBus(private val trailer: Trailer, private val container: Container) Έ͔͡ʔ͍

Slide 20

Slide 20 text

Lambda observable.map(new Func1() { @Override public Bar call(Foo foo) { return foo.toBar(); } }); observable.map(foo -> foo.toBar()); observable.map { foo -> foo.toBar() }

Slide 21

Slide 21 text

Lambda observable.map(new Func1() { @Override public Bar call(Foo foo) { return foo.toBar(); } }); observable.map(foo -> foo.toBar()); observable.map { foo -> foo.toBar() }

Slide 22

Slide 22 text

Lambda observable.map(new Func1() { @Override public Bar call(Foo foo) { return foo.toBar(); } }); observable.map(foo -> foo.toBar()); observable.map { foo -> foo.toBar() }

Slide 23

Slide 23 text

Lambda observable.map(new Func1() { @Override public Bar call(Foo foo) { return foo.toBar(); } }); observable.map(foo -> foo.toBar()); observable.map { foo -> foo.toBar() }

Slide 24

Slide 24 text

ຊ୊

Slide 25

Slide 25 text

Pairsʹ͸ !Activity͕͍ͬͺ͍ ͩͬͨ ͢͝ʔ͍

Slide 26

Slide 26 text

ར༻ٕज़ʹ͍ͭͯ

Slide 27

Slide 27 text

ٕज़֓ཁ Languages Java/Kotlin Network Retrofit2, OkHttp3 O/R Mapper Orma Reactive Programming RxJava1 Dependency Injection Dagger2

Slide 28

Slide 28 text

!Activity?

Slide 29

Slide 29 text

‣ ϏδωεϩδοΫΛ͍࣋ͬͯΔ ‣ IOॲཧ͕͕ͬͭΓॻ͔Ε͍ͯΔ ‣ ͱʹ͔͘ߦ਺͕ଟ͍ !

Slide 30

Slide 30 text

ϏδωεϩδοΫ

Slide 31

Slide 31 text

ϏδωεϩδοΫ if (isPaidUser) { // ༗ྉձһͷΈѻ͑ΔػೳΛ༗ޮԽ͢Δ } else { // ༗ྉձһͷΈѻ͑ΔػೳΛແޮԽ͢Δ }

Slide 32

Slide 32 text

ϏδωεϩδοΫ if (isLikedByPartner) { // ͓૬ख͔Β͍͍Ͷ!Λ΋Β͍ͬͯΔঢ়ଶ } else if (isLikedByMe) { // ͍͍Ͷ!Λ͍ͯ͠Δঢ়ଶ } else if (isLikedWithMessage) { // ϝοηʔδ෇͖͍͍Ͷ!Λ͍ͯ͠Δঢ়ଶ } else if (isLooked) { // ΈͯͶ!Λ͍ͯ͠Δঢ়ଶ } else if (isLookedWithMessage) { // ϝοηʔδ෇͖ΈͯͶ!Λ͍ͯ͠Δঢ়ଶ } else if (isHidden) { // ඇදࣔઃఆΛͨ͠௚ޙ } else if (isBlocked) { // ϒϩοΫઃఆΛͨ͠௚ޙ } else if (...) { ... }

Slide 33

Slide 33 text

‣ ͜Ε͚ͩͳΒ໰୊͸খͦ͞͏ʹΈ͑Δ͕… ‣ ϏδωεϩδοΫ͕ॏͳΓ߹ͬͯɺΞϓϦέʔγϣ ϯ͕࡞ΒΕΔ ‣ ෳ਺ͷϏδωεϩδοΫ͕Activity/Fragment/Adapter ʹ͋;Εͯ͘ΔͱɺίʔυΛ௥͏ͷ͕ࠔ೉ʹ… ϏδωεϩδοΫ

Slide 34

Slide 34 text

IO

Slide 35

Slide 35 text

IO userClient.fetchMathingUsers() .subscribeOnIo() .doOnNex { users -> userDao.insertAll(users) } .onError { userDao.findAll() } .observeOnMain() .subscribe( { users -> showUsers(users) }, { ... })

Slide 36

Slide 36 text

ͱʹ͔͘ߦ਺͕ଟ͍ɺͭΒ͍

Slide 37

Slide 37 text

ఢ͸!ActivityͷΈͳΒͣ

Slide 38

Slide 38 text

‣ ΊͪΌͪ͘Όͳ੹຿ ‣ ਆΫϥε ‣ static͓͡͞Μ ͭΒΈ

Slide 39

Slide 39 text

ΊͪΌͪ͘Όͳ੹຿

Slide 40

Slide 40 text

‣ Converter ‣ JsonΛϚοϐϯάͨ͠Ϋϥε͔ΒɺΞϓϦ಺Ͱ࢖ ͍΍͍͢σʔλΫϥεʹม׵Λߦ͏Ϋϥε ‣ ม׵Λߦ͏͜ͱͷΈ͕੹຿ͷ͸ͣ ΊͪΌͪ͘Όͳ੹຿ class UserConverter { fun convert(res: MatchingUsersResponse): List { return res.users.map { resUser -> User(resUser.name, …) } } }

Slide 41

Slide 41 text

ͳͷ͕ͩ….

Slide 42

Slide 42 text

‣ Convert͢ΔաఔͰϢʔβʔͷϑΟϧλϦϯάΛߦ͏ Converter ΊͪΌͪ͘Όͳ੹຿ class UserConverter { fun convert(res: MatchingUsersResponse): List { return res.users.map { user -> User(user.name, user.age, ...) } .filter { … } } }

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

ਆΫϥε

Slide 45

Slide 45 text

XxxManager ਆΫϥε

Slide 46

Slide 46 text

‣ SearchManager ‣ ݕࡧ৚݅ͷอ࣋ ‣ ݕࡧ݁Ռͷอ࣋ ‣ ݕࡧ݁ՌΛऔಘ͢Δॲཧͷ؅ཧ ‣ … ਆΫϥε

Slide 47

Slide 47 text

‣ ਆʹک͑ ‣ ਆʹفΓ ‣ ਆʹ໋Λ๋͛Δ೔ʑ ਆΫϥε

Slide 48

Slide 48 text

Static͓͡͞Μ

Slide 49

Slide 49 text

‣ API΍DatabaseΛૢ࡞͢ΔϝιουͳͲɺ͍ͨΔͱ͜ ΖͰstaticϝιουΛར༻࣮ͨ͠૷ʹͳ͍ͬͯͨɻ static͓͡͞Μ

Slide 50

Slide 50 text

static͓͡͞Μ public static Observable> fetchMatchingUsers() { return PairsClient.getRetrofit() .create(MatchingUsersService.class) .fetch() ... }

Slide 51

Slide 51 text

static͓͡͞Μ public static Observable> fetchMatchingUsers() { return PairsClient.getRetrofit() .create(MatchingUsersService.class) .fetch() ... }

Slide 52

Slide 52 text

static͓͡͞Μ public static Observable> fetchMatchingUsers() { return PairsClient.getRetrofit() .create(MatchingUsersService.class) .fetch() ... }

Slide 53

Slide 53 text

static͓͡͞Μ public static Observable> fetchMatchingUsers() { return PairsClient.getRetrofit() .create(MatchingUsersService.class) .fetch() ... }

Slide 54

Slide 54 text

‣ ύϑΥʔϚϯε͕ΑΖ͘͠ͳ͍ ‣ “staticϝιου಺ͰstaticϝιουΛ࢖ͬͯRetrofitΛ औಘ͠ɺInterfaceͷ࣮૷ͷੜ੒Λߦ͏”ͱ͍͏ӅΕͨ ೖྗ஋͕͋Δɻ ‣ ӅΕ͍ͯͯ͸ϞοΫ͕Ͱ͖ͳ͍ ‣ UnitςετΉ͔͍ͣ͠… static͓͡͞Μ

Slide 55

Slide 55 text

static͓͡͞Μ class MatchingUsersClient( private val service: MatchingUsersService) { fun fetch(): Observable> { return service.fetch()..... } }

Slide 56

Slide 56 text

΍͹͍!Ͳ͏ʹ͔͠ͳ͍ͱ!

Slide 57

Slide 57 text

EMERGENCY!!

Slide 58

Slide 58 text

‣ Retrofit1->2΁ͷҠߦ࣌ ‣ ຊདྷPOST͢΂͖ͱ͜ΖΛGETʹ͍ͯͨ͠ ‣ ॏཁͳػೳ͕࢖͑ͳ͍ঢ়ଶʹ Emergency

Slide 59

Slide 59 text

‣ ࠓޙಉࣦ͡ഊΛ܁Γฦ͞ͳ͍ͨΊʹ͸? ‣ खಈͷςετ૿΍͢ͷ͸ҙຯ͕ແ͍ΑͶ ‣ ςετίʔυॻ͍ͯࣗಈԽ͍ͨ͠ΑͶɻ Emergency

Slide 60

Slide 60 text

ςετίʔυ
 ॻ͖·͠ΐ͏!

Slide 61

Slide 61 text

Slide 62

Slide 62 text

ॻ͚ͳ͘ͳ͍?

Slide 63

Slide 63 text

‣ ӅΕͨೖྗ஋΍ग़ྗ஋ ‣ ؔΘΓ߹͏staticϝιου ‣ DBʹґଘ͍ͯ͠ΔClient ‣ ෳ਺ͷ໾ׂΛ࣋ͪɺ༷ʑͳঢ়ଶΛ࣋ͭਆʑ ‣ Activityʹॻ͔ΕͨϏδωεϩδοΫୡ ςετͰ͖ͳ͍ΑͶ

Slide 64

Slide 64 text

‣ ੹຿ͷ෼ׂ ‣ !Activityͷվળ ‣ ϏδωεϩδοΫͷഉআ ‣ IOͷഉআ ‣ Staticϝιου܈ͱਆʑʹҾୀ͍ͯͨͩ͘͠ ՝୊

Slide 65

Slide 65 text

େʑతϦϑΝΫλϦϯά

Slide 66

Slide 66 text

Before Entity/Dao Database API Client Activity / Fragment

Slide 67

Slide 67 text

‣ ੹຿͝ͱʹϨΠϠʔΛ෼͚Δ ‣ Retrofit͕ੜ੒͢ΔInterfaceͷ࣮૷Λհͯ͠ɺServerͱ΍ΓऔΓ Λߦ͏Client ‣ Databaseͱ΍ΓऔΓΛߦ͏Dao ‣ σʔλιʔεΛӅṭ͠ɺσʔλͷอଘ/औಘΛߦ͏Repository ‣ ϏδωεϩδοΫΛ࣮ݱ͢ΔUseCase ‣ UseCaseͱViewΛͭͳ͙Presenter ‣ ֤ϨΠϠʔ͸ObservableΛհͯ͠΍ΓऔΓΛߦ͏ ੹຿ͷ෼ׂ

Slide 68

Slide 68 text

After Dao Database API Client Repository UseCase Presenter Activity / Fragment Service

Slide 69

Slide 69 text

After Dao Client Repository UseCase Presenter Activity / Fragment Retrofit͕࣮૷͢ΔInterface Database API Service

Slide 70

Slide 70 text

After Dao Client Repository UseCase Presenter Activity / Fragment Serverͱͷσʔλૹड৴ Database API Service

Slide 71

Slide 71 text

After Dao Client Repository UseCase Presenter Activity / Fragment DBͱͷσʔλૹड৴ Database API Service

Slide 72

Slide 72 text

After Dao Repository UseCase Presenter Activity / Fragment Client σʔλऔಘ/อଘ Database API Service

Slide 73

Slide 73 text

After Dao Repository UseCase Presenter Activity / Fragment Client ϏδωεϩδοΫ Database API Service

Slide 74

Slide 74 text

After Dao Repository UseCase Presenter Activity / Fragment Client ϏδωεϩδοΫͷར༻
 Activity/Fragmentͷૢ࡞ Database API Service

Slide 75

Slide 75 text

After Dao Repository UseCase Presenter Activity / Fragment Client Viewͷૢ࡞
 Activityґଘͷػೳͷૢ࡞ Database API Service

Slide 76

Slide 76 text

After Dao Client Repository UseCase Presenter Activity / Fragment Observable Observable Observable Observable Observable Observable Database API Service

Slide 77

Slide 77 text

Matching

Slide 78

Slide 78 text

Client Dao Client Repository UseCase Presenter Activity / Fragment Database API Service

Slide 79

Slide 79 text

‣ Retrofitʹੜ੒ͤͨ͞Interfaceͷ࣮૷Λར༻ͯ͠௨৴Λ ߦ͏ ‣ JsonͷϚοϐϯάΫϥεΛΞϓϦ಺Ͱར༻͠΍͍͢ σʔλΫϥεʹม׵͢Δ Client

Slide 80

Slide 80 text

Client class UserClient(private val service: UserService) { fun fetchMatchingUsers(offset: Int):Observable> { return service.fetchMatchingUsers(offset) .map { response -> UserConverter.convert(response) } } }

Slide 81

Slide 81 text

Client class UserClient(private val service: UserService) { fun fetchMatchingUsers(offset: Int):Observable> { return service.fetchMatchingUsers(offset) .map { response -> UserConverter.convert(response) } } }

Slide 82

Slide 82 text

Client class UserClient(private val service: UserService) { fun fetchMatchingUsers(offset: Int):Observable> { return service.fetchMatchingUsers(offset) .map { response -> UserConverter.convert(response) } } }

Slide 83

Slide 83 text

Client Test val userService = mock() val client = UserClient(userService) userService.invoked.thenReturn(...) client.fetchMathingUsers().test().run { ... }

Slide 84

Slide 84 text

Dao Dao Client Repository UseCase Presenter Activity / Fragment Database API Service

Slide 85

Slide 85 text

‣ OrmaDatabaseΛར༻ͯ͠Database͔Βσʔλͷऔಘ Λߦ͏ ‣ OrmaDatabaseΛར༻ͯ͠Database΁σʔλΛอଘ͢ Δ Dao

Slide 86

Slide 86 text

Dao class UserDao(private val orma: OrmaDatabase) { fun insert(users: List) { orma.transactionSync { orma.prepareInsertIntoUser(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): Observable> { return orma.selectFromUser() .executeAsObservable() .toList() } }

Slide 87

Slide 87 text

Dao class UserDao(private val orma: OrmaDatabase) { fun insert(users: List) { orma.transactionSync { orma.prepareInsertIntoUser(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): Observable> { return orma.selectFromUser() .executeAsObservable() .toList() } }

Slide 88

Slide 88 text

Dao class UserDao(private val orma: OrmaDatabase) { fun insert(users: List) { orma.transactionSync { orma.prepareInsertIntoUser(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): Observable> { return orma.selectFromUser() .executeAsObservable() .toList() } }

Slide 89

Slide 89 text

Dao class UserDao(private val orma: OrmaDatabase) { fun insert(users: List) { orma.transactionSync { orma.prepareInsertIntoUser(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): Observable> { return orma.selectFromUser() .executeAsObservable() .toList() } }

Slide 90

Slide 90 text

Dao Test val dao = UserDao(orma) dao.insert(...) orma.selectFromUser() .executeAsObservable() .toList() .test() .run { ... } orma.insertIntoUser()… dao.findAll().test().run { ... }

Slide 91

Slide 91 text

Repository Dao Repository UseCase Presenter Activity / Fragment Client Database API Service

Slide 92

Slide 92 text

‣ ClientͱDaoͷͲͪΒ͔͔ΒσʔλͷऔಘΛߦ͏ ‣ Clientܦ༝ͰAPI͔ΒσʔλͷऔಘΛߦͬͨ৔߹ʹ͸ DatabaseʹσʔλΛอଘ͢Δ Repository

Slide 93

Slide 93 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 94

Slide 94 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 95

Slide 95 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 96

Slide 96 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 97

Slide 97 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 98

Slide 98 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 99

Slide 99 text

UserRepository class UserRepository( private val dao: UserDao, private val userClient: UserClient) { fun getMatchingUsers(offset: Int):Observable> { return userClient.fetchMatchingUsers(offset) .doOnNext { users -> dao.insert(users) } .onErrorResumeNext { dao.findAll() } } }

Slide 100

Slide 100 text

UseCase Dao Repository UseCase Presenter Activity / Fragment Client Database API Service

Slide 101

Slide 101 text

‣ ϏδωεϩδοΫΛ࣮ݱ͢Δ UseCase

Slide 102

Slide 102 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLY_USER } else { FacebookPublicSetting.NEITHER } } } }

Slide 103

Slide 103 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLY_USER } else { FacebookPublicSetting.NEITHER } } } }

Slide 104

Slide 104 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLY_USER } else { FacebookPublicSetting.NEITHER } } } }

Slide 105

Slide 105 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLY_USER } else { FacebookPublicSetting.NEITHER } } } }

Slide 106

Slide 106 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLYE_USER } else { FacebookPublicSetting.NEITHER } } } }

Slide 107

Slide 107 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLY_PARTNER } else { FacebookPublicSetting.NEITHER } } } }

Slide 108

Slide 108 text

MatchingUserUseCase class MatchingUserUseCase(private val repo: UserRepository) { fun getUsers(offset: Int) = repo.getMatchingUsers(offset) fun getFacebookPublicSetting( me: Me, user: User): FacebookPublicSetting { return if (shouldShowMeFacebook(me, user)) { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.BOTH } else { FacebookPublicSetting.ONLY_ME } } else { if (shouldShowPartnerFacebook(user)) { FacebookPublicSetting.ONLY_PARTNER } else { FacebookPublicSetting.NEITHER } } } }

Slide 109

Slide 109 text

Presenter Dao Repository UseCase Presenter Activity / Fragment Client Database API Service

Slide 110

Slide 110 text

‣ UseCaseΛར༻ͯ͠ϏδωεϩδοΫΛ࣮ݱ͢Δ ‣ ϏδωεϩδοΫͷ൓өΛActivity/Fragmentʹରͯ͠ ߦ͏ ‣ Activity/Fragmentͱ͸Presenterͷఏڙ͢ΔContractΠ ϯλʔϑΣʔεΛհͯ͠ߦ͏ Presenter

Slide 111

Slide 111 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 112

Slide 112 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 113

Slide 113 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 114

Slide 114 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 115

Slide 115 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 116

Slide 116 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 117

Slide 117 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 118

Slide 118 text

Presenter class MatchingPresenter( private val contract: Contract, private val useCase: MatchingUserUseCase) { fun init() { useCase.getUsers().applySchedulers() .doOnSubscribe { contract.showProgress() } .doOnUnsubscribe { contract.hideProgress() } .subscribe( { users -> contract.showMatchingUsers(users) }, { ... } ) } interface Contract { fun showMatchingUsers(users: List) fun showProgress() fun hideProgress() } }

Slide 119

Slide 119 text

Activity,
 Fragment Dao Repository UseCase Presenter Activity / Fragment Client Database API Service

Slide 120

Slide 120 text

‣ Viewͷૢ࡞ ‣ Activityʹґଘͨ͠ػೳͷϋϯυϦϯά ‣ ͜ΕΒΛPresenterͷ࣋ͭContractΠϯλʔϑΣʔεΛ հͯ͠ఏڙ͢Δ Activity/Fragment

Slide 121

Slide 121 text

Activity/Fragment class MatchingFragment: Fragment(), MatchingPresenter.Contract { … override fun onViewCreated(...) { … presenter.init() } override fun showMatchingUsers(users: List) { listView.adapter = MatchingUsersAdapter(activity, users) } override fun showProgress() { progress.toVisible() } override fun hideProgress() { progress.toGone() } }

Slide 122

Slide 122 text

Activity/Fragment class MatchingFragment: Fragment(), MatchingPresenter.Contract { … override fun onViewCreated(...) { … presenter.init() } override fun showMatchingUsers(users: List) { listView.adapter = MatchingUsersAdapter(activity, users) } override fun showProgress() { progress.toVisible() } override fun hideProgress() { progress.toGone() } }

Slide 123

Slide 123 text

Activity/Fragment class MatchingFragment: Fragment(), MatchingPresenter.Contract { … override fun onViewCreated(...) { … presenter.init() } override fun showMatchingUsers(users: List) { listView.adapter = MatchingUsersAdapter(activity, users) } override fun showProgress() { progress.toVisible() } override fun hideProgress() { progress.toGone() } }

Slide 124

Slide 124 text

Dependency Injection

Slide 125

Slide 125 text

ґଘؔ܎Graph Dao Client Repository UseCase Presenter Activity / Fragment Orma Context Service Retrofit OkHttp

Slide 126

Slide 126 text

‣ Ϋϥε಺Ͱґଘ͢ΔΫϥεͷΠϯελϯεੜ੒Λߦ͏ ͷ͸ྑ͘ͳ͍ ‣ ςετ࣌ʹ੾Γସ͑Δͱ͍ͬͨࣄ͕Ͱ͖ͳ͍ ‣ ֎Ͱੜ੒͠ɺίϯετϥΫλ·ͨ͸ϝϯόʔʹରͯ͠ ґଘੑΛ͍ΕΔ ‣ ґଘੑΛ؅ཧ͢ΔΫϥεΛ࡞Δ ‣ ґଘੑΛ؅ཧ͢ΔΫϥεͷ࣮૷/ϝϯς͕େม ‣ DIΛ࢖͓͏ -> Dagger2 DI

Slide 127

Slide 127 text

Α͠!
 ͜Μͳײ͡Ͱߦ͜͏!

Slide 128

Slide 128 text

‣ Pairs JP AndroidνʔϜ͸౰࣌3ਓ ‣ 2ਓ͸ͦͷ··ࢪࡦͷ࣮૷ ‣ ࢲ͕୲౰ ‣ Pairs Globalͷ@yuyakaidoʹ΋ख఻ͬͯ΋Β͏ ‣ ܭ 1.5ਓ͘Β͍Ͱ࣮૷ Ͳ͏ਐΊ͍ͯͬͨͷ͔

Slide 129

Slide 129 text

‣ ϝΠϯετϦʔϜͱ͸ผʹrefactorϒϥϯν ‣ ϝΠϯετϦʔϜͱͷίϯϑϦΫτΛආ͚ΔͨΊʹ Activity/Fragment΁ͷมߋ͸ඞཁ࠷௿ݶʹ཈͑ͨ ‣ PresenterΛ࣮૷͠ɺActivity/FragmentʹContractΠ ϯλʔϑΣʔεΛ࣮૷͠Α͏ͱࢥ͏ͱɺมߋ͕๲ େʹͳΔͷͰPresenterͷ࣮૷͸ޙճ͠ʹ ‣ Activity/Fragment͸Ұ୴UseCaseΛ௚Ͱѻ͏͜ͱΛ ڐ༰ Ͳ͏ਐΊ͍ͯͬͨͷ͔

Slide 130

Slide 130 text

Ͳ͏ਐΊ͍ͯͬͨͷ͔ ‣ ґଘؔ܎Graphͷϧʔτ͔Βมߋ ΛՃ͍͑ͯ͘ ‣ ·ͣ͸Dagger2ͷModule/ ComponentΛ࡞੒ɻ ‣ OkHttp, Retrofit, Ormaͷprovideϝ ιουΛ࣮૷

Slide 131

Slide 131 text

‣ σʔλιʔε͝ͱʹDao, Client, RepositoryΛ࣮૷ ‣ UserDao, UserClient, UserRepository ‣ MeDao, MeClient, MeRepository ‣ … ‣ σʔλιʔε͝ͱʹɺRepository͕࣮૷׬ྃ࣍ୈ UseCaseΛ࣮૷ ‣ Activity/FragmentʹมߋΛՃ͑Δ Ͳ͏ਐΊ͍ͯͬͨͷ͔ ‘͓૬ख’ͷσʔλΫϥε ‘ࣗ෼’ͷσʔλΫϥε

Slide 132

Slide 132 text

‣ ͍͖ͳΓΰʔϧΛ໨ࢦ͞ͳ͍ ‣ ग़དྷΔݶΓਖ਼ৗಈ࡞͢Δঢ়ଶΛอͭ ‣ খ͍͞มߋΛੵΈॏͶ͍ͯ͘ ‣ ΠϯλʔϑΣʔε͕มΘΔͱݺͼग़͠ݩͷมߋ΋ඞ ཁʹͳΔͷͰɺҰ୴ճΓಓͯ͠໨తΛୡ੒͢Δ ‣ ͦͷޙʹΠϯλʔϑΣʔεΛमਖ਼ͯ͠ݺͼग़͠ݩ΁ ͷมߋΛߦ͍ͬͯ͘ େ੾ͳ͜ͱ

Slide 133

Slide 133 text

‣ ৽͍͠ઃܭʹؔͯ͠νʔϜϝϯόʔ͕ཧղͰ͖Δ·Ͱ ͬ͘͡Γͱڭ͑Δ ‣ ͍ͭͰ΋ಡΈฦͤΔΑ͏ʹɺQiita:teamͳͲʹ·ͱΊ ͓ͯ͘ େ੾ͳ͜ͱ

Slide 134

Slide 134 text

1.5ϲ݄ޙ…

Slide 135

Slide 135 text

Release

Slide 136

Slide 136 text

վળޙ

Slide 137

Slide 137 text

‣ ςετίʔυ͕֨ஈʹॻ͖΍͘͢ͳͬͨ ‣ શମͷݟ௨͕͠ྑ͘ͳͬͨ ‣ ԿॲʹɺԿΛॻ͚͹Α͍ͷ͔͕෼͔Γ΍͍͢ ‣ ԿॲʹɺԿ͕͋Δͷ͔͕෼͔Γ΍͍͢ ‣ ϥΠϒϥϦͷࡌͤସ͕͑༰қʹͳΓͦ͏ ‣ e.g. ORMΛࡌͤସ͍͑ͨͱͳͬͨΒDao΁ͷมߋ ͚ͩͰ׬݁͢Δ ͜ͷ࣮૷ͷϝϦοτ

Slide 138

Slide 138 text

‣ Ϋϥε਺ɺϝιου਺͕ଟ͍ ‣ Dex Countࢯʙ ‣ ࣮૷ίετ ‣ ֶशίετ ͜ͷ࣮૷ͷσϝϦοτ

Slide 139

Slide 139 text

Conclusion

Slide 140

Slide 140 text

‣ Dao, Client, Repository, UseCaseͳͲ੹຿͝ͱʹϨΠ ϠʔΛ෼͚ͨ ‣ ModelͱViewͷؒʹPresenterΛઃ͚ͯViewͱModelΛ ໌֬ʹ෼͚Δ ‣ Dagger2ʹґଘੑͷղܾΛҕৡ͢Δ ‣ σʔλιʔε͝ͱʹԼͷϨΠϠʔ͔Βॱʹ࣮૷͍ͯ͠ ͘ ‣ ϝϯόʔ΁ͷϨΫνϟʔ͸͔ܽ͞ͳ͍ ‣ จͱͯ͠࢒͠ɺ͍ͭͰ΋ݟฦ͢Α͏ʹͨ͠ ·ͱΊ

Slide 141

Slide 141 text

Thank you