Slide 1

Slide 1 text

ࢿ࢈ӡ༻ελʔτΞοϓͷ։ൃͰ࠾༻ͨ͠ 1MBZʹΑΔ$MFBO"SDIJUFDUVSFͰͷ ઃܭɾ։ൃࣄྫ גࣜձࣾΫϥ΢υϙʔτ एদ ܚ৴ ˏ4DBMBؔ੢ 4VNNJU 4DBMBؔ੢ 4VNNJU

Slide 2

Slide 2 text

4QFBLFS גࣜձࣾΫϥ΢υϙʔτ एদ ܚ৴ !ZTIOC 普段やっていること • Scalaによるバックエンドも含む開発・運⽤など 4DBMBؔ੢ 4VNNJU

Slide 3

Slide 3 text

0VUMJOF • ࢿ࢈ӡ༻αʔϏεͷ։ൃഎܠ • $MFBO"SDIJUFDUVSFͱͦͷղऍ • 'VOETͷΞʔΩςΫνϟͱ࣮૷ͷ۩ମྫ • ·ͱΊ 4DBMBؔ੢ 4VNNJU

Slide 4

Slide 4 text

0VUMJOF • ࢿ࢈ӡ༻αʔϏεͷ։ൃഎܠ • $MFBO"SDIJUFDUVSFͱͦͷղऍ • 'VOETͷΞʔΩςΫνϟͱ࣮૷ͷ۩ମྫ • ·ͱΊ 4DBMBؔ੢ 4VNNJU

Slide 5

Slide 5 text

ࠓճࣄྫΛ࿩͢ࢿ࢈ӡ༻αʔϏε 4DBMBؔ੢ 4VNNJU

Slide 6

Slide 6 text

資産形成をしたい個⼈とお⾦を借りたい企業を結ぶ、 「貸付ファンド」のオンラインマーケット 第⼆種⾦融商品取引業者のクラウドポートが運営

Slide 7

Slide 7 text

4DBMBؔ੢ 4VNNJU

Slide 8

Slide 8 text

ϑΝϯυ ૊੒اۀ ౤ࢿՈ आΓखاۀ ϑΝϯυ΁ग़ࢿ ି෇ ͓ۚΛି͢ お⾦を集める 'VOETͷ͘͠Έ 4DBMBؔ੢ 4VNNJU

Slide 9

Slide 9 text

ϑΝϯυ ૊੒اۀ ౤ࢿՈ आΓखاۀ ϑΝϯυ΁ग़ࢿ ି෇ ෼഑ ฦࡁ རଉΛؚΊͯ ͓ۚΛฦ͢ ӡ༻͞Εͨ ͓ۚΛड͚औΔ 'VOETͷ͘͠Έ 4DBMBؔ੢ 4VNNJU

Slide 10

Slide 10 text

αʔϏε։ൃͷഎܠ 4DBMBؔ੢ 4VNNJU

Slide 11

Slide 11 text

αʔϏε։ൃͷલఏ৚݅ • اըʙϩʔϯν·Ͱ൒೥ఔ౓ͷ։ൃظؒʢ౰ॳ༧ఆʣ • ۚ༥αʔϏεͳΒͰ͸ͷෳࡶͳυϝΠϯ • ূ݊ձࣾɾܾࡁαʔϏεͳͲͱ͸ҟͳΓɺ طଘͷۚ༥αʔϏεͱͷ઀ଓ͸ඞཁͳ͍ 4DBMBؔ੢ 4VNNJU

Slide 12

Slide 12 text

։ൃ͢ΔνʔϜͷঢ়گ • αʔόαΠυͰ͸ͳ͘શମͰΤϯδχΞ໊ • ։ൃνʔϜͰϞχλϦϯάͳͲͷӡ༻΋୲౰ • ӡ༻։࢝ޙͷਓతͳӡ༻ෛՙ͕௿͍͜ͱ͕ॏཁ 4DBMBؔ੢ 4VNNJU

Slide 13

Slide 13 text

γεςϜΞʔΩςΫνϟ #BDLFOE4FSWJDF 4DBMB DB, Datastore, External REST Services, etc. 4FSWJDFGSPOUFOE "ENJOGSPOUFOE 3&45"1* 3&45"1* 4DBMBؔ੢ 4VNNJU

Slide 14

Slide 14 text

γεςϜΞʔΩςΫνϟ #BDLFOE4FSWJDF 4DBMB DB, Datastore, External REST Services, etc. 4FSWJDFGSPOUFOE "ENJOGSPOUFOE ౤ࢿՈ޲͚ ΢ΣϒαΠτ 3&45"1* 3&45"1* ࣾ಺޲͚ ΦϖϨʔγϣϯը໘ αʔϏε͝ͱʹಠཱɾૄ݁߹ͳϑϩϯτΤϯυ 4DBMBؔ੢ 4VNNJU

Slide 15

Slide 15 text

γεςϜΞʔΩςΫνϟ #BDLFOE4FSWJDF 4DBMB DB, Datastore, External REST Services, etc. 4FSWJDFGSPOUFOE "ENJOGSPOUFOE 3&45"1* 3&45"1* ڞ௨όοΫΤϯυ αʔϏε υϝΠϯ͕ෳࡶɾີ઀ʹؔ܎͢ΔόοΫΤϯυ͸ ϞϊϦγοΫͳαʔϏεͰߏ੒ 4DBMBؔ੢ 4VNNJU

Slide 16

Slide 16 text

ϞϊϦγοΫͳΞʔΩςΫνϟͷ࠾༻ • αʔόαΠυͰ͸ͳ͘શମͰΤϯδχΞ໊ • ։ൃνʔϜͰϞχλϦϯάͳͲͷӡ༻΋୲౰ • ӡ༻։࢝ޙͷਓతͳӡ༻ෛՙ͕௿͍͜ͱ͕ॏཁ ڽूੑͷߴ͍ϓϩδΣΫτͷํ͕ޮ཰͕Α͍ 4DBMBؔ੢ 4VNNJU

Slide 17

Slide 17 text

ϞϊϦγοΫͳΞʔΩςΫνϟͷ࠾༻ • υϝΠϯͷؔ܎੔ཧ͸೉͍͠ • ޡͬͨίϯςΩετͷ෼ׂ͸ෳࡶ͚ͩ͞ΛߴΊͯ͠·͏ ΞΧ΢ϯτ ϑΝϯυ ސ٬࣋෼ ,:$ ஫จ ೖग़ۚ υϝΠϯ಺ͷؔ܎ੑ͕੔ཧ͞ΕΔ·Ͱมߋίετͷ௿͍ߏ଄Λ࠾༻͍ͨ͠ σϙδοτ࢒ߴ ࢿۚҠಈ ސ٬ 'VOETʹ͓͚ΔίϯςΩετͷྫ 4DBMBؔ੢ 4VNNJU

Slide 18

Slide 18 text

ϞϊϦγοΫͳΞʔΩςΫνϟͷ࠾༻ • ϞϊϦγοΫͳΞʔΩςΫνϟͰ΋มԽʹରԠ͍ͨ͠ • ίϯςΩετͰ͸ͳ͘ந৅౓ΑΔ෼ྨ͸ൺֱతཧղ͠΍͍͢ ΞϓϦέʔγϣϯΞʔΩςΫνϟͱͯ͠$MFBO"SDIJUFDUVSFΛ׆༻ 4DBMBؔ੢ 4VNNJU

Slide 19

Slide 19 text

0VUMJOF • ࢿ࢈ӡ༻αʔϏεͷ։ൃഎܠ • $MFBO"SDIJUFDUVSFͱͦͷղऍ • 'VOETͷΞʔΩςΫνϟͱ࣮૷ͷ۩ମྫ • ·ͱΊ 4DBMBؔ੢ 4VNNJU

Slide 20

Slide 20 text

$MFBO"SDIJUFDUVSFͱͦͷղऍ 4DBMBؔ੢ 4VNNJU

Slide 21

Slide 21 text

4DBMBؔ੢ 4VNNJU

Slide 22

Slide 22 text

ந৅౓ʹΑΔϨΠϠʔͷ෼཭ ç 4DBMBؔ੢ 4VNNJU

Slide 23

Slide 23 text

$MFBO"SDIJUFDUVSFͰఆٛ͞ΕΔϨΠϠʔ ϨΠϠʔ ϨΠϠʔͷ֓ཁ &OUJUZ &OUFSQSJTF#VTJOFTT3VMFT اۀશମͷϏδωεϧʔϧ 6TF$BTF "QQMJDBUJPO#VTJOFTT3VMFT ΞϓϦέʔγϣϯݻ༗ͷϧʔϧɾϩδοΫ *OUFSGBDF"EBQUFST ೖग़ྗɾӬଓԽɾ%#ඇґଘͷ42-ͳͲ 'SBNFXPSLT%SJWFST ϑϨʔϜϫʔΫ΍υϥΠόͳͲ 4DBMBؔ੢ 4VNNJU

Slide 24

Slide 24 text

%FQFOEFODZ3VMF ಉ৺ԁͷ֎ଆͷϨΠϠʔ͔Β಺ଆͷϨΠϠʔ΁ Ұํ޲ͷґଘʢٯํ޲ͷґଘΛೝΊͳ͍ʣ ç $MFBO"SDIJUFDUVSFʹ͓͚Δॏཁͳίϯηϓτ 4DBMBؔ੢ 4VNNJU

Slide 25

Slide 25 text

%FQFOEFODZ3VMFͱґଘؔ܎ٯసͷݪଇ • ґଘؔ܎ٯసͷݪଇʢ%*1ʣ40-*%ͷݪଇͷͭ • ৄࡉ͕ந৅ʹґଘ͢΂͖ • $MFBO"SDIJUFDUVSFʹ͓͚Δ%FQFOEFODZ3VMF • %*1ΛΑΓ۩ମతͳܗͰड़΂ͨ΋ͷ 4DBMBؔ੢ 4VNNJU

Slide 26

Slide 26 text

ಉ৺ԁͷ಺ଆΛ௨ա͢Δ੍ޚͷྲྀΕ ç 4DBMBؔ੢ 4VNNJU

Slide 27

Slide 27 text

ΠϯλʔϑΣΠεʹΑΔ੍ޚͷ൓స • ಺ଆ͔Β֎ଆͷϞδϡʔϧΛݺͼग़͢ඞཁ͕͋Δ৔߹ʹ ಺ଆͷϨΠϠʔʹΠϯλʔϑΣΠεΛఆٛ • ֎ଆͷϨΠϠʔͰ͸಺ଆͰఆٛ͞Εͨ ΠϯλʔϑΣΠεʹରͯ͠۩ମత࣮૷Λ༩͑Δ 4DBMBؔ੢ 4VNNJU

Slide 28

Slide 28 text

$MFBO"SDIJUFDUVSFͷΤοηϯε • ந৅౓ʹԠͯ͡ϨΠϠʔΛ෼཭͢Δ • %FQFOEFODZ3VMFͰந৅౓ͷߴ͍ํ޲΁ґଘͤ͞Δ • ಺ଆˠ֎ଆͱ͍͏੍ޚͷྲྀΕΛ࣮ݱ͢ΔͨΊʹ ΠϯλʔϑΣΠεΛ׆༻͢Δ 4DBMBؔ੢ 4VNNJU

Slide 29

Slide 29 text

0VUMJOF • ࢿ࢈ӡ༻αʔϏεͷ։ൃഎܠ • $MFBO"SDIJUFDUVSFͱͦͷղऍ • 'VOETͷΞʔΩςΫνϟͱ࣮૷ͷ۩ମྫ • ·ͱΊ 4DBMBؔ੢ 4VNNJU

Slide 30

Slide 30 text

'VOETʹ͓͚Δ$MFBO"SDIJUFDUVSF $MFBO"SDIJUFDUVSFͷΤοηϯεΛ׆༻͠ ٕज़తͳৄࡉ͔Β෼཭ͨ͠ΞϓϦέʔγϣϯͷઃܭ΁ 4DBMBؔ੢ 4VNNJU

Slide 31

Slide 31 text

'VOETͰ࠾༻͍ͯ͠ΔϨΠϠʔߏ଄ ϨΠϠʔ ϨΠϠʔͷ֓ཁ %PNBJO υϝΠϯݻ༗ͷ֓೦ɾϏδωεϩδοΫ "QQMJDBUJPO ΞϓϦέʔγϣϯݻ༗ͷϩδοΫ *OUFSGBDF ೖग़ྗ΍ͦͷදݱ *OGSBTUSVDUVSF ෭࡞༻Λ࣮࣋ͭ૷ ʢ%# 3&454FSWJDF FUD 4DBMBؔ੢ 4VNNJU

Slide 32

Slide 32 text

*OGSBTUSVDUVSF *OUFSGBDFT "QQMJDBUJPO %PNBJO ϨΠϠʔͷґଘؔ܎ ্ҐϨΠϠʔ͔Β ԼҐϨΠϠʔͷґଘ͸ೝΊΔ ϨΠϠʔΛ·͙ͨґଘ΋ೝΊΔ ԼҐϨΠϠʔ͔Β্ҐϨΠϠʔͷ ґଘ͸ೝΊͳ͍ 4DBMBؔ੢ 4VNNJU

Slide 33

Slide 33 text

੍ޚͷྲྀΕͱΠϯλʔϑΣΠε • ੍ޚͷྲྀΕ্Ґ ˠ ԼҐʢந৅΁ͷґଘʣ • ΠϯλʔϑΣΠεΛ໌ࣔతʹఆٛͤͣ௚઀ݺͼग़͠ • ࣮૷͔Β෼཭͢ΔԸܙ͕গͳ͍ͱ൑அ • ੍ޚͷྲྀΕԼҐ ˠ ্Ґʢৄࡉ΁ͷґଘʣ • ݪଇ௨ΓԼҐϨΠϠʔͰΠϯλʔϑΣΠεΛఆٛɾ࣮૷Λ༩͑Δ 4DBMBؔ੢ 4VNNJU

Slide 34

Slide 34 text

ύοέʔδͷશମ૾ ϨΠϠʔͷ ύοέʔδߏ੒ ͦͷଞͷύοέʔδ 4DBMBؔ੢ 4VNNJU

Slide 35

Slide 35 text

࣮૷ύλʔϯͷ۩ମྫ • 1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ • 3FQPTJUPSZͷઃܭͱ*OGSBTUSVDUVSFͷ࣮૷ • ΞϓϦέʔγϣϯʹ͓͚Δ%* 4DBMBؔ੢ 4VNNJU

Slide 36

Slide 36 text

࣮૷ύλʔϯͷ۩ମྫ • 1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ • 3FQPTJUPSZͷઃܭͱ*OGSBTUSVDUVSFͷ࣮૷ • ΞϓϦέʔγϣϯʹ͓͚Δ%* 4DBMBؔ੢ 4VNNJU

Slide 37

Slide 37 text

1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ *OGSBTUSVDUVSF *OUFSGBDFT "QQMJDBUJPO %PNBJO 1MBZΛ࢖༻͢ΔϨΠϠʔ $POUSPMMFS 6TF$BTF 4DBMBؔ੢ 4VNNJU

Slide 38

Slide 38 text

1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ 3FRVFTU.PEFM +40/ 6TF$BTF +40/ 3FTQPOTF.PEFM 2VFSZ $POUSPMMFS "DUJPO JOUFSGBDF BQQMJDBUJPO 4DBMBؔ੢ 4VNNJU

Slide 39

Slide 39 text

੍ޚͷྲྀΕ$POUSPMMFS "DUJPO 3FRVFTU.PEFM +40/ 6TF$BTF +40/ 3FTQPOTF.PEFM 2VFSZ $POUSPMMFS "DUJPO JOUFSGBDF BQQMJDBUJPO 4DBMBؔ੢ 4VNNJU

Slide 40

Slide 40 text

੍ޚͷྲྀΕ$POUSPMMFS "DUJPO def getList: Action[AnyContent] = asyncSecuredJsonAction(defaultRoles) { implicit request => ... usecase.fetchCustomerList.perform(customerCondition).map { case (customers, count) => Response(200, ListResponse(count, customers.map(CustomerCardDetailResponseModel.apply))) } } • 1MBZͷ$POUSPMMFS "DUJPO Λ࢖༻ • ೖग़ྗܗࣜͷม׵ͱ6TF$BTFͷݺͼग़͠ʹݶఆ͢Δ࣮૷ϧʔϧ 4DBMBؔ੢ 4VNNJU

Slide 41

Slide 41 text

੍ޚͷྲྀΕ6TF$BTF 3FRVFTU.PEFM +40/ 6TF$BTF +40/ 3FTQPOTF.PEFM 2VFSZ $POUSPMMFS "DUJPO JOUFSGBDF BQQMJDBUJPO 4DBMBؔ੢ 4VNNJU

Slide 42

Slide 42 text

੍ޚͷྲྀΕ6TF$BTF case class FetchCustomerList()( implicit val customerRepository: CustomerReadRepository, implicit val ec: ExecutionContext ) extends UseCase { def perform(customerCondition: CustomerQueryCondition): Future[(Seq[Customer], Int)] = { for { customers <- customerRepository.findByCondition(customerCondition) count <- customerRepository.countByCondition(customerCondition) } yield { (customers, count) } } } • ΞϓϦέʔγϣϯݻ༗ͷಈ࡞Λ࣮૷ • 6TF$BTF୯ҐͰΫϥεΛ෼཭ 4DBMBؔ੢ 4VNNJU

Slide 43

Slide 43 text

੍ޚͷྲྀΕ3FTQPOTF.PEFM 3FRVFTU.PEFM +40/ 6TF$BTF +40/ 3FTQPOTF.PEFM 2VFSZ $POUSPMMFS "DUJPO JOUFSGBDF BQQMJDBUJPO 4DBMBؔ੢ 4VNNJU

Slide 44

Slide 44 text

੍ޚͷྲྀΕ3FTQPOTF.PEFM • ϨεϙϯεͷܕΛDBTFDMBTTͰఆٛ • &OUJUZ͋Δ͍͸ͦͷू໿͔Β3FTQPOTF.PEFMΛड͚औΓγϦΞϥΠζ case class CustomerStatusResponseModel( code: String, name: String, ) extends ResponseModel object CustomerStatusResponseModel { import CustomerPresenter._ def apply(status: CustomerStatus) = { new CustomerStatusResponseModel( status.code, status.name ) } } 4DBMBؔ੢ 4VNNJU

Slide 45

Slide 45 text

4XBHHFSͷ࢓༷ͱ࣮૷্ͷܕͷ౷Ұ case class CustomerStatusResponseModel( code: String, name: String, ) extends ResponseModel object CustomerStatusResponseModel { import CustomerPresenter._ def apply(status: CustomerStatus) = { new CustomerStatusResponseModel( status.code, status.name ) } } 4XBHHFS্Ͱͷఆٛ 4XBHHFSͰఆٛͨ͠ܕͱΞϓϦέʔγϣϯ্Ͱ࣮૷͢Δํͷ౷Ұ ΞϓϦέʔγϣϯ্ͷ࣮૷ 4DBMBؔ੢ 4VNNJU

Slide 46

Slide 46 text

࣮૷ύλʔϯͷ۩ମྫ • 1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ • 3FQPTJUPSZͷઃܭͱ*OGSBTUSVDUVSFͷ࣮૷ • ΞϓϦέʔγϣϯʹ͓͚Δ%* 4DBMBؔ੢ 4VNNJU

Slide 47

Slide 47 text

3FQPTJUPSZͷઃܭͱ*OGSBTUSVDUVSFͷ࣮૷ *OGSBTUSVDUVSF *OUFSGBDFT "QQMJDBUJPO %PNBJO %"0 3&45$MJFOU FUD 3FQPTJUPSZ 4DBMBؔ੢ 4VNNJU

Slide 48

Slide 48 text

%PNBJO υϝΠϯݻ༗ͷ֓೦ɾ ϏδωεϩδοΫΛදݱ͢ΔϨΠϠʔ *OGSBTUSVDUVSF *OUFSGBDFT "QQMJDBUJPO %PNBJO ओͳߏ੒ཁૉ • &OUJUZ 7BMVF0CKFDU΋ؚΉʣ • %PNBJO4FSWJDF • 3FQPTJUPSZ 4DBMBؔ੢ 4VNNJU

Slide 49

Slide 49 text

3FQPTJUPSZ • ӬଓԽɾӬଓԽ͞ΕͨσʔλͷࢀরΛఏڙ͢ΔΠϯλʔϑΣΠε • %#͚ͩͰͳ͘3&454FSWJDF $MJFOUͳͲɺ ෭࡞༻Λ൐͏೚ҙͷૢ࡞ͷΠϯλʔϑΣΠεͱͯ͠ఆٛ trait CustomerReadRepository extends ReadRepository with CustomerBaseRepository trait CustomerBaseRepository { def findCustomers: Future[Seq[Customer]] } 4DBMBؔ੢ 4VNNJU

Slide 50

Slide 50 text

trait CustomerRepository extends ReadWriteRepository with CustomerBaseRepository { def save(customer: Customer): Future[ID[Customer]] } trait CustomerReadRepository extends ReadRepository with CustomerBaseRepository trait CustomerBaseRepository { def findCustomers: Future[Seq[Customer]] } SFBEPOMZ SFBEXSJUFՄೳ SFBEPOMZXSJUBCMFͳΠϯλʔϑΣΠε෼཭ 4DBMBؔ੢ 4VNNJU

Slide 51

Slide 51 text

class FindCustomers( implicit val customerRepository: CustomerReadRepository, val ec: ExecutionContext, ) extends UseCase { def perform(): Future[Seq[Customer]] = { ... val customersF = customerRepository.findCustomers ... } } ಡΈऔΓઐ༻Ͱ͋Δ͜ͱ͕ อূ͞Ε͍ͯΔ ੍ݶͷ͋Δ࣮૷Λద༻Մೳ ʢFHSFBEFSFOEQPJOUͷ࢖༻ SFBEPOMZXSJUBCMFͳΠϯλʔϑΣΠε෼཭ 4DBMBؔ੢ 4VNNJU

Slide 52

Slide 52 text

*OGSBTUSVDUVSF࣮૷ͷྫ • %#BDDFTT 4MJDL • 3FEJT • 3&454FSWJDF )551 • 4.51 • ϚωʔδυαʔϏεʢ"NB[PO424 4 ,.4 FUDʣ 4DBMBؔ੢ 4VNNJU

Slide 53

Slide 53 text

*OGSBTUSVDUVSFͷ࣮૷ྫ4MJDL • 'VOETͰ͸%#BDDFTTʹ4MJDLΛ࠾༻ • ͦͷଞͷબ୒ࢶRVJMM 4DBMJLF+%#$ FUD 4DBMBؔ੢ 4VNNJU

Slide 54

Slide 54 text

*OGSBTUSVDUVSFͷ࣮૷ྫ4MJDL trait CustomerTable extends ColumnMappers { this: Profile => import profile.api._ class Customers(tag: Tag) extends Table[CustomerRow](tag, "customer") { def id = column[ID[Customer]]("id", O.SqlType("INT"), O.PrimaryKey, O.AutoInc) def email = column[String]("email", O.SqlType("VARCHAR(256)")) def status = column[CustomerStatus]("status", O.SqlType("INT")) ... type TableRecord = (Option[ID[Customer]], String, CustomerStatus) def * = (id.?, email, status) <> ( (t: TableRecord) => { val (id, email, status_) = t CustomerRow(id, email, status) }, (customer: CustomerRow) => { Option((customer.id, customer.email, customer.status)) } ) } } 4DBMBؔ੢ 4VNNJU

Slide 55

Slide 55 text

*OGSBTUSVDUVSFͷ࣮૷ྫ4MJDL class CustomerDAO(val dbConfig: DatabaseConfig[JdbcProfile])(implicit val ec: ExecutionContext) extends CustomerDAOLike with Profile with DefaultSlickDBConfig trait CustomerDAOLike extends CustomerRepository with CustomerReadRepository with CustomerTable this: Profile with SlickDBConfig[JdbcProfile] => def save(customer: Customer) = { val query = customerQuery += customer db.run(query.transactionally) } ... } 4DBMBؔ੢ 4VNNJU

Slide 56

Slide 56 text

*OGSBTUSVDUVSFͷ࣮૷ྫ3&45 4FSWJDF trait CustomerRestServiceLike extends CustomerReadRepository { implicit val ec: ExecutionContext val client: WSClient val baseUrl: String lazy val baseUrl = s”..." def findCustomers: Future[Seq[Customer]] = { val requestUrl = s"$baseUrl/customer" for { response <- client.url(requestUrl).get() } yield { val results = for { ... } yield result } results.flatten } } } 4DBMBؔ੢ 4VNNJU

Slide 57

Slide 57 text

*OGSBTUSVDUVSFͷ࣮૷ͱަ׵Մೳੑ • Ͳͷٕज़తৄࡉͰ΋3FQPTJUPSZΛ࣮૷ʢ·ͨ͸࣮૷Մೳʣ • ϏδωεϩδοΫΛมߋ͢Δ͜ͱͳٕ͘ज़తৄࡉΛมߋͰ͖Δ • ύϑΥʔϚϯεͷվળ • 3FQPTJUPSZΛڥքͱͨ͠αʔϏεͷ෼ׂ 4DBMBؔ੢ 4VNNJU

Slide 58

Slide 58 text

࣮૷ύλʔϯͷ۩ମྫ • 1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ • 3FQPTJUPSZͷઃܭͱ*OGSBTUSVDUVSFͷ࣮૷ • ΞϓϦέʔγϣϯʹ͓͚Δ%* 4DBMBؔ੢ 4VNNJU

Slide 59

Slide 59 text

)PXUP%* • 4DBMBʹ͓͚Δબ୒ࢶ͸ (VJDF .BDXJSF FUD • 'VOETͰ͸͋͑ͯ*NQMJDJUQBSBNFUFSʹΑΔ%*Λ࢖༻ 4DBMBؔ੢ 4VNNJU

Slide 60

Slide 60 text

ΞϓϦέʔγϣϯͷॳظԽ ֤छΠϯελϯεͷॳظԽͱ %*ʹΑΔґଘϞδϡʔϧΛղܾ͢Δ ύοέʔδ *OUFSGBDFT "QQMJDBUJPO %PNBJO *OGSBTUSVDUVSF 3VOUJNF 4DBMBؔ੢ 4VNNJU

Slide 61

Slide 61 text

*NQMJDJUQBSBNFUFSʹΑΔ%* • ܕ҆શੑͷԸܙΛಘΒΕΔ੩త%*Λ࠾༻͍ͨ͠ • ಉҰͷΠϯλʔϑΣΠεʹෳ਺ͷ࣮૷ΛJOKFDU͍ͨ͠ • ௨ৗ͸JNQMJDJUQBSBNFUFSͰσϑΥϧτͷ࣮૷ΛJOKFDU • ಛఆͷγʔϯͰ͸໌ࣔతʹࢦఆ࣮ͨ͠૷ΛJOKFDU 4DBMBؔ੢ 4VNNJU

Slide 62

Slide 62 text

*NQMJDJUQBSBNFUFSʹΑΔ%* trait InfrastructureComponents extends DatabaseComponents with CacheLayerComponents with S3Components ... { this: BuiltInComponentsFromContext => } ϨΠϠʔ୯ҐͰͷ$PNQPOFOUʹNJYJO trait DatabaseComponents extends SlickComponents { this: BuiltInComponentsFromContext => implicit lazy val customerDAO: CustomerRepository = new CustomerDAO(dbConfig) implicit lazy val customerReadDAO: CustomerReadRepository = new CustomerDAO(slaveDbConfig) ... } ύοέʔδ͝ͱͷΠϯελϯεॳظԽΛఆٛ 4DBMBؔ੢ 4VNNJU

Slide 63

Slide 63 text

*NQMJDJUQBSBNFUFSʹΑΔ%* class ApplicationComponents(context: Context) extends BuiltInComponentsFromContext(context) with I18nComponents with HttpFiltersComponents with AdminControllerComponents with ServiceControllerComponents with InfrastructureComponents { ... } ֤ϨΠϠʔͷ$PNQPOFOUTΛ"QQMJDBUJPO$PNQPOFOUT΁NJYJO class MainApplicationLoader extends ApplicationLoader { def load(context: Context): Application = { new ApplicationComponents(context).application } } "QQMJDBUJPO-PBEFSͷఆٛ 4DBMBؔ੢ 4VNNJU

Slide 64

Slide 64 text

ಉҰΠϯλʔϑΣΠε্ͷ࣮૷ͷަ׵ trait DatabaseComponents extends SlickComponents { this: BuiltInComponentsFromContext => implicit lazy val customerDAO: CustomerRepository = new CustomerDAO(dbConfig) implicit lazy val customerReadDAO: CustomerReadRepository = new CustomerDAO(slaveDbConfig) } σϑΥϧτͰղܾ͞ΕΔ࣮૷ʢJNQMJDJU lazy val adminCustomerComponents = new CustomerComponents { import CustomerComponents._ val fetchCustomerList = FetchCustomerList() ... } *NQMJDJUQBSBNFUFSʹΑΔ%* 4DBMBؔ੢ 4VNNJU

Slide 65

Slide 65 text

ಉҰΠϯλʔϑΣΠε্ͷ࣮૷ͷަ׵ ίϯετϥΫλύϥϝʔλͰ࣮૷Λ໌ࣔతʹࢦఆ lazy val adminCustomerComponents = new CustomerComponents { import CustomerComponents._ val fetchCustomerList = FetchCustomerList(cachedCustomerDAO, ec) ... } trait CacheLayerComponents { this: BuiltInComponentsFromContext with RedisComponents with DatabaseComponents => lazy val cachedCustomerDAO: CusotmerReadRepository = new CustomerRedisCache(customerReadDAO)(redisClient, executionContext) } ҟͳΔ࣮૷ͷྫʢΩϟογϡʣ 4DBMBؔ੢ 4VNNJU

Slide 66

Slide 66 text

0VUMJOF • ࢿ࢈ӡ༻αʔϏεͷ։ൃഎܠ • $MFBO"SDIJUFDUVSFͱͦͷղऍ • 'VOETͷΞʔΩςΫνϟͱ࣮૷ͷ۩ମྫ • ·ͱΊ 4DBMBؔ੢ 4VNNJU

Slide 67

Slide 67 text

·ͱΊ • αʔϏεͱ$MFBO"SDIJUFDUVSFͷݕ౼എܠʹ͍ͭͯ • ΞϓϦέʔγϣϯͱ۩ମతͳ࣮૷ύλʔϯͷྫΛ঺հ • 1MBZ'SBNFXPSLΛ׆༻͢Δ੍ޚͷྲྀΕ • 3FQPTJUPSZͷઃܭͱ*OGSBTUSVDUVSFͷ࣮૷ • ΞϓϦέʔγϣϯʹ͓͚Δ%* 4DBMBؔ੢ 4VNNJU

Slide 68

Slide 68 text

͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 4DBMBؔ੢ 4VNNJU