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

ゲンバのクリーンアーキテクチャ - Scala play プロジェクト設計のお話 -

Yad
March 26, 2016

ゲンバのクリーンアーキテクチャ - Scala play プロジェクト設計のお話 -

2016/03/26 Developers.IO 2016 in Osaka #cmdevio2016 発表資料

Yad

March 26, 2016
Tweet

More Decks by Yad

Other Decks in Programming

Transcript

  1.  ҆ୡɹ༐Ұ • 2013/12 ೖࣾ • TwitterID: @UsrNameu1 • Github:

    https://github.com/ UsrNameu1 • Blog: http://dev.classmethod.jp/ author/yad • ͜͜Ұ೥͸αʔόʔαΠυϝΠϯ
  2.  ⡥$MBTTNFUIPE *OD ʮؔ৺ͷ෼཭ʯΛ໨తͱ͢Δ༷ʑͳΞʔΩςΫνϟ Λ୯Ұͷ֓೦ʹ౷߹ w ϔΩαΰφϧΞʔΩςΫνϟ  ๜༁ॻɿ࣮ફςετۦಈ։ൃʣ w

    ΦχΦϯΞʔΩςΫνϟ ݩهࣄɿIUUQKF⒎SFZQBMFSNPDPNCMPHUIFPOJPOBSDIJUFDUVSFQBSUʣ w %BUB$POUFYU*OUFSBDUJPO  ༸ॻɿ-FBOBSDIJUFDUVSFʣ w #PVOEBSZ $POUSPM &OUJUZ  ๜༁ॻɿΦϒδΣΫτࢦ޲ιϑτ΢ΣΞ޻ֶ004&ʣ
  3. w σʔλϕʔεɺ6*ɺ"1**'ɺ֎෦γεςϜͷػೳʹ࠷΋ศ རͳܗࣜʹσʔλΛม׵ $POUSPMMFS %"0  w ֤ػೳͷΞμϓλ͸ϢʔεέʔεΛ௨ͯ͡ଞͷΞμϓλͱ΍ ΓऔΓ͢ΔʢଞͷػೳͷΞμϓλΛ௚઀஌Βͳ͍ʣ w

    ֤ػೳʹݻ༗ͷσʔλߏ଄ ɹ͸͜͜Ͱ಺෦ʢϢʔεέʔεɾ ɹΤϯςΟςΟʣͷѻ͍΍͍͢ ɹσʔλߏ଄ʹม׵͞ΕΔ  ⡥$MBTTNFUIPE *OD ΠϯλʔϑΣΠεΞμϓλʔ &OUJUJFT 6TFDBTFT *OUFSGBDFBEBQUFS %# 6* "1**' ֎෦γεςϜ '8
  4.  ⡥$MBTTNFUIPE *OD ΫϦʔϯΞʔΩςΫνϟ͸ ϑϨʔϜϫʔΫ͔Βಠཱͨ͠γεςϜΛੜΈग़͢ ΫϦʔϯΞʔΩςΫνϟͷޮ༻ &OUJUJFT %"0 $POUSPMMFS 6TFDBTFT

    'SBNFXPSL -JCSBSZ 4%, &YUFSOBM "1*$MJFOU "84 $MJFOU 4FSWJDF 6TFDBTFTΑΓ ಺ଆͷϨΠϠ͸ ϑϨʔϜϫʔΫ౳ͷ มߋʹӨڹΛड͚ͳ͍
  5.  ⡥$MBTTNFUIPE *OD ΫϦʔϯΞʔΩςΫνϟ͸ 6*ɺ"1*ͷ*'͔Βಠཱͨ͠γεςϜΛੜΈग़͢ &OUJUJFT %"0 $POUSPMMFS 6TFDBTFT 6*ɾ"1**'

    &YUFSOBM "1*$MJFOU "84 $MJFOU 4FSWJDF 6TFDBTFTΑΓ ಺ଆͷϨΠϠ͸ 6*ɺ"1**'ͷ มߋʹӨڹΛ ड͚ͳ͍
  6.  ⡥$MBTTNFUIPE *OD ΫϦʔϯΞʔΩςΫνϟ͸ σʔλϕʔε͔Βಠཱͨ͠γεςϜΛੜΈग़͢ ⡥$MBTTNFUIPE *OD &OUJUJFT %"0 $POUSPMMFS

    6TFDBTFT %# $BDIF &YUFSOBM "1*$MJFOU "84 $MJFOU 4FSWJDF  6TFDBTFTΑΓ ಺ଆͷϨΠϠ͸ %# $BDIFͷ มߋʹӨڹΛ ड͚ͳ͍
  7.  ⡥$MBTTNFUIPE *OD ΫϦʔϯΞʔΩςΫνϟ͸ ֎෦ػೳ͔Βಠཱͨ͠γεςϜΛੜΈग़͢ &OUJUJFT %"0 $POUSPMMFS 6TFDBTFT ֎෦"1*

    ֎෦γεςϜ &YUFSOBM "1*$MJFOU "84 $MJFOU 4FSWJDF 6TFDBTFTΑΓ ಺ଆͷϨΠϠ͸ ֎෦"1*ɺγεςϜͷ มߋʹӨڹΛ ड͚ͳ͍
  8.  ⡥$MBTTNFUIPE *OD ΫϦʔϯΞʔΩςΫνϟ͸ ςελϏϦςΟʹ༏ΕͨγεςϜΛੜΈग़͢ %# $BDIF 6*ɾ"1**' &OUJUJFT %"0

    $POUSPMMFS 4FSWJDF 4UPSF ֎෦ʹ௚઀ґଘ͍ͯ͠ͳ͍ͨΊ 6TFDBTFT &OUJUJFT ͷςετʹ͸ ୯७ͳϞοΫͱ ࣄલ৚݅ͷΈ͕ඞཁ
  9. ࣮ࡍͷϓϩδΣΫτύοέʔδߏ੒ྫ  ⡥$MBTTNFUIPE *OD ։ൃ؀ڥ w +BWB w 4DBMB w

    TCU w QMBZ w BXTTEL ༻్ w େ͖ͳμ΢ϯϩʔυ਺͕૝ఆ͞ΕΔϞόΠϧΞϓϦͷ όοΫΤϯυ"1*
  10. ࣮ࡍͷϓϩδΣΫτύοέʔδߏ੒ྫ  ⡥$MBTTNFUIPE *OD !"" app $"" controllers $"" core

    $"" domains $"" infrastructures $"" modules !"" services *OUFSGBDF"EBQUFSϨΠϠ 6TFDBTFTϨΠϠ &OUJUJFTϨΠϠ $PSFϨΠϠ %*ίϯςφઃఆ
  11. !"" controllers !"" someendpoint $"" RequestBodyConverter.scala $"" ResponseBodyConverter.scala $"" SomeEndpointController.scala

    !"" SomeEndpointResultGenerator.scala  ⡥$MBTTNFUIPE *OD DPOUSPMMFST഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ "1**'ʹؔΘΔػೳΛఏڙͨ͠ ύοέʔδͱϨΠϠͷରԠ
  12. !"" controllers !"" someendpoint $"" RequestBodyConverter.scala $"" ResponseBodyConverter.scala $"" SomeEndpointController.scala

    !"" SomeEndpointResultGenerator.scala  ⡥$MBTTNFUIPE *OD DPOUSPMMFST഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ "1**'ʹؔΘΔػೳΛఏڙͨ͠ +TPO㱻&OUJUZͷม׵Λ୲͏3FBET 8SJUFT͕ هड़͞Εͨίϯόʔλ ύοέʔδͱϨΠϠͷରԠ
  13. !"" controllers !"" someendpoint $"" RequestBodyConverter.scala $"" ResponseBodyConverter.scala $"" SomeEndpointController.scala

    !"" SomeEndpointResultGenerator.scala  ⡥$MBTTNFUIPE *OD DPOUSPMMFST഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ "1**'ʹؔΘΔػೳΛఏڙͨ͠ +TPO㱻&OUJUZͷม׵Λ୲͏3FBET 8SJUFT͕ هड़͞Εͨίϯόʔλ 3PVUFT΁ͷϦΫΤετΛࡹ͘ίϯτϩʔϥ ύοέʔδͱϨΠϠͷରԠ
  14. !"" controllers !"" someendpoint $"" RequestBodyConverter.scala $"" ResponseBodyConverter.scala $"" SomeEndpointController.scala

    !"" SomeEndpointResultGenerator.scala  ⡥$MBTTNFUIPE *OD DPOUSPMMFST഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ "1**'ʹؔΘΔػೳΛఏڙͨ͠ +TPO㱻&OUJUZͷม׵Λ୲͏3FBET 8SJUFT͕ هड़͞Εͨίϯόʔλ 3PVUFT΁ͷϦΫΤετΛࡹ͘ίϯτϩʔϥ ಺෦ɺ֎෦Ͱग़ͨΤϥʔΛΤϥʔϨεϙϯεʹม׵͢ΔϞδϡʔϧ ύοέʔδͱϨΠϠͷରԠ
  15.  ⡥$MBTTNFUIPE *OD !"" infrastructures !"" somesystem $"" apiclients $""

    awsclients !"" dbclients JOGSBTUSVDUVSFT഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ %#$BDIF &YUFSOBM"1* "84΁ͷػೳΛఏڙͨ͠
  16. !"" infrastructures !"" somesystem $"" apiclients $"" awsclients !"" dbclients

     ⡥$MBTTNFUIPE *OD JOGSBTUSVDUVSFT഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ %#$BDIF &YUFSOBM"1* "84΁ͷػೳΛఏڙͨ͠ ֎෦"1*΁ͷΞΫηεΛ୲͏"1*ΫϥΠΞϯτ܈
  17. !"" infrastructures !"" somesystem $"" apiclients $"" awsclients !"" dbclients

     ⡥$MBTTNFUIPE *OD JOGSBTUSVDUVSFT഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ %#$BDIF &YUFSOBM"1* "84΁ͷػೳΛఏڙͨ͠ ֎෦"1*΁ͷΞΫηεΛ୲͏"1*ΫϥΠΞϯτ܈ %#Ҏ֎ͷ"84αʔϏε΁ͷΞΫηεΛ୲͏ΫϥΠΞϯτ܈
  18. !"" infrastructures !"" somesystem $"" apiclients $"" awsclients !"" dbclients

     ⡥$MBTTNFUIPE *OD JOGSBTUSVDUVSFT഑ԼύοέʔδͰ͸ *OUFSGBDF"EBQUFSϨΠϠͷ͏ͪ %#$BDIF &YUFSOBM"1* "84΁ͷػೳΛఏڙͨ͠ ֎෦"1*΁ͷΞΫηεΛ୲͏"1*ΫϥΠΞϯτ܈ %#౳΁ͷΞΫηεΛ୲͏%"0܈ %#Ҏ֎ͷ"84αʔϏε΁ͷΞΫηεΛ୲͏ΫϥΠΞϯτ܈
  19.  ⡥$MBTTNFUIPE *OD !"" services !"" someusecase $"" SomeModelStore.scala !""

    FindSomeModelService.scala TFSWJDFT഑ԼύοέʔδͰ͸ 6TFDBTFTϨΠϠͷϏδωεɾϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠
  20. !"" services !"" someusecase $"" SomeModelStore.scala !"" FindSomeModelService.scala  ⡥$MBTTNFUIPE

    *OD TFSWJDFT഑ԼύοέʔδͰ͸ 6TFDBTFTϨΠϠͷϏδωεɾϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠ σʔλετΞந৅ʢUSBJU 
  21. !"" services !"" someusecase $"" SomeModelStore.scala !"" FindSomeModelService.scala  ⡥$MBTTNFUIPE

    *OD TFSWJDFT഑ԼύοέʔδͰ͸ 6TFDBTFTϨΠϠͷϏδωεɾϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠ σʔλετΞந৅ʢUSBJU  4PNF.PEFMऔಘαʔϏε
  22.  ⡥$MBTTNFUIPE *OD !"" domains !"" somemodel $"" SomeModel.scala $""

    SomeModelRepository.scala $"" SomeModelRegistration.scala !"" PublishSomeModelIdService.scala EPNBJOT഑ԼύοέʔδͰ͸ &OUJUJFTϨΠϠͷσʔλߏ଄ɺϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠
  23.  ⡥$MBTTNFUIPE *OD !"" domains !"" somemodel $"" SomeModel.scala $""

    SomeModelRepository.scala $"" SomeModelRegistration.scala !"" PublishSomeModelIdService.scala EPNBJOT഑ԼύοέʔδͰ͸ &OUJUJFTϨΠϠͷσʔλߏ଄ɺϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠ 4PNF.PEFMΛද͢σʔλߏ଄
  24.  ⡥$MBTTNFUIPE *OD !"" domains !"" somemodel $"" SomeModel.scala $""

    SomeModelRepository.scala $"" SomeModelRegistration.scala !"" PublishSomeModelIdService.scala EPNBJOT഑ԼύοέʔδͰ͸ &OUJUJFTϨΠϠͷσʔλߏ଄ɺϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠ σʔλετΞந৅ʢUSBJU  4PNF.PEFMΛද͢σʔλߏ଄
  25.  ⡥$MBTTNFUIPE *OD !"" domains !"" somemodel $"" SomeModel.scala $""

    SomeModelRepository.scala $"" SomeModelRegistration.scala !"" PublishSomeModelIdService.scala EPNBJOT഑ԼύοέʔδͰ͸ &OUJUJFTϨΠϠͷσʔλߏ଄ɺϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠ σʔλετΞந৅ʢUSBJU  4PNF.PEFMΛද͢σʔλߏ଄ 4PNF.PEFMͷొ࿥Λද͢σʔλߏ଄
  26.  ⡥$MBTTNFUIPE *OD !"" domains !"" somemodel $"" SomeModel.scala $""

    SomeModelRepository.scala $"" SomeModelRegistration.scala !"" PublishSomeModelIdService.scala EPNBJOT഑ԼύοέʔδͰ͸ &OUJUJFTϨΠϠͷσʔλߏ଄ɺϧʔϧ ֎෦ϨΠϠͰ࣮૷͢Δந৅Λఏڙͨ͠ σʔλετΞந৅ʢUSBJU  4PNF.PEFMΛද͢σʔλߏ଄ 4PNF.PEFMͷొ࿥Λද͢σʔλߏ଄ 4PNF.PEFMͷ*EൃߦΛ͢ΔαʔϏε
  27.  ⡥$MBTTNFUIPE *OD ͦͷଞ೰Μͩͱ͜Ζ w ৽ͨͳϑΟʔϧυͷ௥Ճ͸ଟ͘ͷ৔߹ɺ&OUJUJFTͷϑΟʔ ϧυʹӨڹͨ͠ɻ w ڥք͝ͱͷσʔλߏ଄ʢ%50ʣ͸͋·Γఆٛͤͣɺґଘϧʔ ϧతʹ͸໰୊͕ͳ͍ͱߟ͑ɺ*OUFSGBDF"EBQUFS΋

    &OUJUJFTͷσʔλߏ଄Λར༻ͨ͠ɻʢهࣄ಺Ͱ͸ਪ঑͞Ε ͍ͯͳ͍ʣ w ಉ༷ʹ%*1͸6TFDBTFT૚Λ·͕ͨͬͯ&OUJUJFTͷσʔλ ετΞந৅Λ௚઀*OUFSGBDF"EBQUFS͕࣮૷͢Δ͜ͱ͕ ͋ͬͨɻ
  28.  ⡥$MBTTNFUIPE *OD ͦͷଞ೰Μͩͱ͜Ζ w 9994FSWJDFͱ͍͏໊લͷϏδωεϩδοΫΛ6TF DBTFTϨΠϠ͔&OUJUJFTϨΠϠʹஔ͔͘Ͱ໎ͬͨɻ w 6TFDBTFTϨΠϠͷϩδοΫ͕ಉ͡Α͏ͳՕॴͰ͔ͭͦΕ ͕ϓϩδΣΫτશମͱͯ͠ڞ௨ʹ༻͍ΒΕͦ͏ͳ֓೦ͷ৔

    ߹ɺ&OUJUJFTʹ͓͘ͱ͍͏҉໧ͷج४͸͋ͬͨɻ w ϓϩδΣΫτશମͰͷڞ༻ϥΠϒϥϦͰ΋ڞ௨ͷ *OUFSGBDF"EBQUFS͕͋ͬͨͨΊɺڞ༻ϥΠϒϥϦͷύο έʔδߏ੒͸ΞϓϦέʔγϣϯͱಉ͡Α͏ͳ΋ͷʹͳͬͨɻ
  29.  ⡥$MBTTNFUIPE *OD %*1ʢґଘੑٯసͷݪଇʣ &OUJUJFT %"0 $POUSPMMFS 4FSWJDF 6* "1**'

    4UPSF %*1 %# $BDIF લड़ͷ௨ΓɺΫϦʔϯΞʔΩςΫνϟʹ͸%*1͕ඞཁ
  30. (VJDFʹΑΔ%*ͱ%*1ͷ࣮૷ྫ  ⡥$MBTTNFUIPE *OD &OUJUJFT %"0 $POUSPMMFS 4FSWJDF "1**' 4UPSF

    %*$POUBJOFS DPOG %*1 $BDIF ԼͷΑ͏ͳΞϓϦέʔγϣϯΛ%*Λ༻͍࣮ͯ૷͢Δ
  31.  ⡥$MBTTNFUIPE *OD 6TFDBTFTϨΠϠͷσʔλετΞந৅ trait SomeModelStore { def findById( identifier:

    String ): Future[Option[SomeModel]] } 6TFDBTFTϨΠϠͷந৅σʔλετΞ͸ USBJUͰ࣮૷ͨ͠
  32.  ⡥$MBTTNFUIPE *OD 6TFDBTFTϨΠϠͷσʔλετΞந৅ trait SomeModelStore { def findById( identifier:

    String ): Future[Option[SomeModel]] } *%Λࢦఆͯ͠ ϞσϧΛಘΔ ͳ͚Ε͹/POF 6TFDBTFTϨΠϠͷந৅σʔλετΞ͸ USBJUͰ࣮૷ͨ͠
  33.  ⡥$MBTTNFUIPE *OD 6TFDBTFTϨΠϠͷ4FSWJDF࣮૷ class FindSomeModelService @Inject()( store: SomeModelStore )

    { def findById( identifier: String ): Future[Option[SomeModel]] = store.findById(identifier) }
  34.  ⡥$MBTTNFUIPE *OD 6TFDBTFTϨΠϠͷ4FSWJDF࣮૷ class FindSomeModelService @Inject()( store: SomeModelStore )

    { def findById( identifier: String ): Future[Option[SomeModel]] = store.findById(identifier) } 4FSWJDF͸%*͞Εͨ6TFDBTFTϨΠϠͷ ந৅σʔλετΞΛར༻͢Δ
  35.  ⡥$MBTTNFUIPE *OD 6TFDBTFTϨΠϠͷ4FSWJDF࣮૷ class FindSomeModelService @Inject()( store: SomeModelStore )

    { def findById( identifier: String ): Future[Option[SomeModel]] = store.findById(identifier) } 4FSWJDF͸%*͞Εͨ6TFDBTFTϨΠϠͷ ந৅σʔλετΞΛར༻͢Δ 4FSWJDF͸ந৅σʔλετΞಉ࢜ͷ ୯७ͳ૊Έ߹ΘͤΛ࣮૷͢Δ
  36.  ⡥$MBTTNFUIPE *OD *OUFSGBDF"EBQUFSϨΠϠͷ%"0ʢ3FEJTʣ class SomeModelDAO @Inject()( @Named("some_model") pool: RedisClientPool

    ) extends SomeModelStore { import CacheJsonConverters._ override def findById( identifier: String ): Future[Option[SomeModel]] = Future { pool.withClient { client => val maybeJson = client.get(identifier) map Json.parse maybeJson map { Json.fromJson(_).get } } } }
  37.  ⡥$MBTTNFUIPE *OD *OUFSGBDF"EBQUFSϨΠϠͷ%"0ʢ3FEJTʣ class SomeModelDAO @Inject()( @Named("some_model") pool: RedisClientPool

    ) extends SomeModelStore { import CacheJsonConverters._ override def findById( identifier: String ): Future[Option[SomeModel]] = Future { pool.withClient { client => val maybeJson = client.get(identifier) map Json.parse maybeJson map { Json.fromJson(_).get } } } } !/BNFEλάʹΑͬͯ%*͢ΔΠϯελϯεͷ ੍ޚΛߦ͑Δ
  38.  ⡥$MBTTNFUIPE *OD *OUFSGBDF"EBQUFSϨΠϠͷ%"0ʢ3FEJTʣ class SomeModelDAO @Inject()( @Named("some_model") pool: RedisClientPool

    ) extends SomeModelStore { import CacheJsonConverters._ override def findById( identifier: String ): Future[Option[SomeModel]] = Future { pool.withClient { client => val maybeJson = client.get(identifier) map Json.parse maybeJson map { Json.fromJson(_).get } } } } !/BNFEλάʹΑͬͯ%*͢ΔΠϯελϯεͷ ੍ޚΛߦ͑Δ 6TFDBTFTϨΠϠͷந৅Λ %"0͸࣮૷͢Δ
  39.  ⡥$MBTTNFUIPE *OD *OUFSGBDF"EBQUFSϨΠϠͷ%"0ʢ3FEJTʣ class SomeModelDAO @Inject()( @Named("some_model") pool: RedisClientPool

    ) extends SomeModelStore { import CacheJsonConverters._ override def findById( identifier: String ): Future[Option[SomeModel]] = Future { pool.withClient { client => val maybeJson = client.get(identifier) map Json.parse maybeJson map { Json.fromJson(_).get } } } } !/BNFEλάʹΑͬͯ%*͢ΔΠϯελϯεͷ ੍ޚΛߦ͑Δ 6TFDBTFTϨΠϠͷந৅Λ %"0͸࣮૷͢Δ จࣈྻˠ+TPOˠϞσϧʹม׵ͯ͠ Ξ΢τϓοτ
  40.  ⡥$MBTTNFUIPE *OD class SomeModelController @Inject()( findService: FindSomeModelService ) extends

    Controller { import ResponseBodyConverters._ def find(identifier: String) = Action.async { for { maybeModel <- findService.findById(identifier) result = maybeModel match { case None => NotFound case Some(model) => Ok(Json.toJson(model)) } } yield result } } *OUFSGBDF"EBQUFSϨΠϠͷ$POUSPMMFS
  41.  ⡥$MBTTNFUIPE *OD class SomeModelController @Inject()( findService: FindSomeModelService ) extends

    Controller { import ResponseBodyConverters._ def find(identifier: String) = Action.async { for { maybeModel <- findService.findById(identifier) result = maybeModel match { case None => NotFound case Some(model) => Ok(Json.toJson(model)) } } yield result } } *OUFSGBDF"EBQUFSϨΠϠͷ$POUSPMMFS %*͞Εͨ6TFDBTFTϨΠϠͷ αʔϏεΛར༻͢Δ
  42.  ⡥$MBTTNFUIPE *OD class SomeModelController @Inject()( findService: FindSomeModelService ) extends

    Controller { import ResponseBodyConverters._ def find(identifier: String) = Action.async { for { maybeModel <- findService.findById(identifier) result = maybeModel match { case None => NotFound case Some(model) => Ok(Json.toJson(model)) } } yield result } } Ϟσϧˠ+TPOʹม׵ͯ͠ϨεϙϯεΛฦ٫ *OUFSGBDF"EBQUFSϨΠϠͷ$POUSPMMFS %*͞Εͨ6TFDBTFTϨΠϠͷ αʔϏεΛར༻͢Δ
  43.  ⡥$MBTTNFUIPE *OD %*ίϯςφͷઃఆΫϥε class AppDependencyModule extends AbstractModule { override

    def configure(): Unit = { bind(classOf[SomeModelStore]).to(classOf[SomeModelDAO]) } @Provides @Singleton @Named("some_model") def provideStoreDetailRedisClientPool( configuration: Configuration ): RedisClientPool = new RedisClientPool( configuration.getString("redis.host").get, configuration.getInt("redis.port").get, database = 1 ) }
  44.  ⡥$MBTTNFUIPE *OD %*ίϯςφͷઃఆΫϥε class AppDependencyModule extends AbstractModule { override

    def configure(): Unit = { bind(classOf[SomeModelStore]).to(classOf[SomeModelDAO]) } @Provides @Singleton @Named("some_model") def provideStoreDetailRedisClientPool( configuration: Configuration ): RedisClientPool = new RedisClientPool( configuration.getString("redis.host").get, configuration.getInt("redis.port").get, database = 1 ) } "CTUSBDU.PEVMFΛܧঝͯ͠ઃఆΫϥεΛͭ͘Δ
  45.  ⡥$MBTTNFUIPE *OD %*ίϯςφͷઃఆΫϥε class AppDependencyModule extends AbstractModule { override

    def configure(): Unit = { bind(classOf[SomeModelStore]).to(classOf[SomeModelDAO]) } @Provides @Singleton @Named("some_model") def provideStoreDetailRedisClientPool( configuration: Configuration ): RedisClientPool = new RedisClientPool( configuration.getString("redis.host").get, configuration.getInt("redis.port").get, database = 1 ) } 4FSWJDFͰ%*͞ΕΔσʔλετΞந৅ʹରͯ͠ ͲͷΫϥε͕ ஫ೖ͞ΕΔ͔ એݴ͢Δ "CTUSBDU.PEVMFΛܧঝͯ͠ઃఆΫϥεΛͭ͘Δ
  46.  ⡥$MBTTNFUIPE *OD %*ίϯςφͷઃఆΫϥε class AppDependencyModule extends AbstractModule { override

    def configure(): Unit = { bind(classOf[SomeModelStore]).to(classOf[SomeModelDAO]) } @Provides @Singleton @Named("some_model") def provideStoreDetailRedisClientPool( configuration: Configuration ): RedisClientPool = new RedisClientPool( configuration.getString("redis.host").get, configuration.getInt("redis.port").get, database = 1 ) } 4FSWJDFͰ%*͞ΕΔσʔλετΞந৅ʹରͯ͠ ͲͷΫϥε͕ ஫ೖ͞ΕΔ͔ એݴ͢Δ "CTUSBDU.PEVMFΛܧঝͯ͠ઃఆΫϥεΛͭ͘Δ %"0Ͱ༻͍Δ 3FEJT઀ଓͷͨΊͷ ΫϥεΛઃఆ
  47.  ⡥$MBTTNFUIPE *OD )0$0/ )VNBO0QUJNJ[FE$POpH0CKFDU /PUBUJPO ϑΥʔϚοτͰએݴ͞Εͨ %*ίϯςφͷઃఆΫϥεରԠDPOGϑΝΠϧ redis {

    host = "localhost" port = "6379" } play.modules.enabled += modules.AppDependencyModule 3FEJTʹ༻͍ΔIPTU QPSUએݴ QMBZͷΞϓϦέʔγϣϯʹ ઌ΄Ͳͷ%*ઃఆΫϥεΛಡΈ͜·ͤΔ
  48.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' $POUSPMMFSɺ֎෦"1*ͷ Ϩεϙϯε+TPOίϯόʔλ ʹ৽͍͠ϑΟʔϧυͷ ௥Ճ
  49.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' &OUJUJFTͷ Ϟσϧσʔλߏ଄ʹ ৽͍͠ϑΟʔϧυΛ௥Ճ $POUSPMMFSɺ֎෦"1*ͷ Ϩεϙϯε+TPOίϯόʔλ ʹ৽͍͠ϑΟʔϧυͷ ௥Ճ
  50.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' &OUJUJFTͷ Ϟσϧσʔλߏ଄ʹ ৽͍͠ϑΟʔϧυΛ௥Ճ $POUSPMMFSɺ֎෦"1*ͷ Ϩεϙϯε+TPOίϯόʔλ ʹ৽͍͠ϑΟʔϧυͷ ௥Ճ ϑΟʔϧυಛ༗ͷϩδοΫΛ ॻ͔ͳ͔ͬͨ 6TFDBTFTϨΠϠ͸ ࡞༻ͷӨڹΛड͚ͳ͍
  51.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' ࠷৽ͷ৘ใऔಘ ΤϯυϙΠϯτ޲͚ ΞΫγϣϯΛ௥Ճ
  52.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' ࠷৽ͷ৘ใߋ৽"1* ΫϥΠΞϯτΛ௥Ճ ࠷৽ͷ৘ใऔಘ ΤϯυϙΠϯτ޲͚ ΞΫγϣϯΛ௥Ճ
  53.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' ࠷৽ͷ৘ใߋ৽"1* ΫϥΠΞϯτΛ௥Ճ ࠷৽৘ใऔಘ αʔϏεΛ ௥Ճ ࠷৽ͷ৘ใऔಘ ΤϯυϙΠϯτ޲͚ ΞΫγϣϯΛ௥Ճ
  54.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT ֎෦"1* &YUFSOBM "1*$MJFOU

    4FSWJDF "1**' &OUJUJFTͷ Ϟσϧσʔλߏ଄͸ ߏ଄Խ͞Ε͍ͯΔͨΊ ࡞༻ͷӨڹΛड͚ͳ͍ ࠷৽ͷ৘ใߋ৽"1* ΫϥΠΞϯτΛ௥Ճ ࠷৽৘ใऔಘ αʔϏεΛ ௥Ճ ࠷৽ͷ৘ใऔಘ ΤϯυϙΠϯτ޲͚ ΞΫγϣϯΛ௥Ճ
  55.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT "84ɹ $MPVE'SPOU "84$MJFOU

    4FSWJDF "1**' 4ͷΩʔ໊͔Βͷ ॺ໊͖ͭ63- ൃߦػೳΛ 4ͷΩʔ໊͔Β $MPVE'SPOUͷ63-ʹ ม׵͢Δػೳʹमਖ਼
  56.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT "84ɹ $MPVE'SPOU "84$MJFOU

    4FSWJDF "1**' &OUJUJFTͷ αʔϏεͷ໊લ͕࣮ଶͱ ဃ཭ͯ͠͠·ͬͨͨΊ मਖ਼͕ൃੜͨ͠ 4ͷΩʔ໊͔Βͷ ॺ໊͖ͭ63- ൃߦػೳΛ 4ͷΩʔ໊͔Β $MPVE'SPOUͷ63-ʹ ม׵͢Δػೳʹमਖ਼
  57.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT "84ɹ $MPVE'SPOU "84$MJFOU

    4FSWJDF "1**' &OUJUJFTͷ αʔϏεͷ໊લ͕࣮ଶͱ ဃ཭ͯ͠͠·ͬͨͨΊ मਖ਼͕ൃੜͨ͠ 4ͷΩʔ໊͔Βͷ ॺ໊͖ͭ63- ൃߦػೳΛ 4ͷΩʔ໊͔Β $MPVE'SPOUͷ63-ʹ ม׵͢Δػೳʹमਖ਼ &OUJUJFTͷมߋʹ߹Θͤͨ ίʔυͷमਖ਼͕ൃੜ
  58.  ⡥$MBTTNFUIPE *OD Ͳ͏޲͖߹͔ͬͨ &OUJUJFT $POUSPMMFS 6TFDBTFT "84ɹ $MPVE'SPOU "84$MJFOU

    4FSWJDF "1**' &OUJUJFTͷ αʔϏεͷ໊લ͕࣮ଶͱ ဃ཭ͯ͠͠·ͬͨͨΊ मਖ਼͕ൃੜͨ͠ 4ͷΩʔ໊͔Βͷ ॺ໊͖ͭ63- ൃߦػೳΛ 4ͷΩʔ໊͔Β $MPVE'SPOUͷ63-ʹ ม׵͢Δػೳʹमਖ਼ &OUJUJFTͷมߋʹ߹Θͤͨ ίʔυͷमਖ਼͕ൃੜ "1**'मਖ਼͕ͳ͍ͨΊ ࡞༻ͷӨڹΛड͚ͳ͍
  59.  ⡥$MBTTNFUIPE *OD ૝ఆ͞ΕΔ&OUJUJFTϨΠϠͷαʔϏεʹؔ͢ΔԾઆ w &OUJUJFTϨΠϠͷαʔϏεʹରͯ͠ɺʮॺ໊͖ͭ63-ൃ ߦʯͱ͍͏۩ମతͳ໊લΛ͚ͭͯ͠·ͬͨ͜ͱʹΑͬͯɺ େن໛ͳमਖ਼͕ൃੜͨ͠ͱߟ͑ΒΕΔ w αʔϏεͷ໊લ͕࠷ॳ͔Βʮ63-ม׵ʯͩͬͨΒେن໛ͳ

    ม׵͸ى͜Βͳ͔͔ͬͨ΋͠Εͳ͍ w Αͬͯɺ&OUJUJFTϨΠϠͷαʔϏεʹରͯ͠͸Πϯϑϥʹ ґଘ͠ͳ͍Α͏ͳɺΑΓϏδωεϩδοΫͱͯ͠ͷந৅౓ ͷߴ໊͍લΛ͚ͭͨํ͕Α͔͔ͬͨ΋͠Εͳ͍