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

リアクティブDDD

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for かとじゅん かとじゅん
September 29, 2016

 リアクティブDDD

Avatar for かとじゅん

かとじゅん

September 29, 2016
Tweet

More Decks by かとじゅん

Other Decks in Technology

Transcript

  1. ࣗݾ঺հ w ͔ͱ͡ΎΜ !KJLP  w $IBU8PSL͔ࣾΒདྷ·ͨ͠ɻ w ࢓ࣄ͸$IBU8PSLαʔόج൫෦෼ͷ৽ن։ൃ w

    ઐ໳෼໺ʁ w υϝΠϯۦಈઃܭ w ࠷ۙ͸ϦΞΫςΟϒγεςϜʁ w ࠷ۙݚᮎ͍ͯ͠Δ͜ͱ w 4DBMB"LLB %%% w "OHVMBSc3FBDU  %%%
  2. ':*%%%ͱ"LLBͷؔ࿈ੑ w &⒎FDUJWF"LLB w $IBQUFS"DUPS"QQMJDBUJPO5ZQFT w %PNBJOESJWFO w "DUPS͸%%%Ͱࣔ͞ΕΔίϯηϓ τΛදݱͰ͖Δɻͨͱ͑͹ɺΤϯ

    ςΟςΟ΍ू໿ͳͲɻ"DUPSͱڥք ͚ͮΒΕͨίϯςΩετΛσβΠ ϯͰ͖Δ w %%%ͷϝοηʔδ͸ࣄ࣮ʹجͮ͘ɻ ϝοηʔδύογϯάͰ͸ੈքͰ ىͬͨ͜ग़དྷࣄΛϝοηʔδͱ͠ ͯදݱ͢Δɻ͜Ε͸ϕετϓϥΫ ςΟεɻ w 8PSL%JTUSJCVUJPO
  3. എܠʹ͍ͯ͠ΔίϯςΩετͷมԽ w αʔό୆਺ͷมԽ w ਺े୆͔Β਺ઍίΞ΁ w Ԡ౴࣌ؒͷมԽ w ඵ͔ΒϛϦඵΦʔμʔ΁ w

    μ΢ϯλΠϜͷมԽ w ਺͔࣌ؒΒݶΓͳ࣌ؒ͘΁ w σʔλن໛ͷมԽ w ΪΨ͔Βϖλ΁
  4. ࢧ͑Δݪཧ ఏڙ͢ΔՁ஋ લఏͱͳΔखஈ ϦΞΫςΟϒએݴ w IUUQXXXSFBDUJWFNBOJGFTUPPSH w ʹެ։͞Εͨએݴɻ໊ ͕ॺ໊ɻ-JHIUCFOEࣾͷ$50 +POBT#POÉSࢯ͕'JSTU"VUIPSɻ

    w ଈԠੑ 3FTQPOTJWF  w γεςϜ͸ՄೳͳݶΓ଎΍͔ʹԠ ౴͢Δɻ w ଱ো֐ੑ 3FTJMJFOU  w γεςϜ͸ো֐ʹ௚໘ͯ͠΋ଈԠ ੑΛอͪଓ͚Δɻ ଈԠੑ ϝοηʔδۦಈ ଱ো֐ੑ ஄ྗੑ w ஄ྗੑ &MBTUJD  w γεςϜ͸ϫʔΫϩʔυ͕ม ಈͯ͠΋ଈԠੑΛอͪଓ͚Δɻ w ϝοηʔδۦಈ .FTTBHF %SJWFO  w ίϯϙʔωϯτؒΛඇಉظ ʹϝοηʔδΛૹड৴͢Δ ௨৴ελΠϧɻϝοηʔδ ύογϯάͱ΋ݴΘΕΔɻ
  5. ':*ιϑτ΢ΣΞͷࡂ͍Λද͢༻ޠ w ޡࠩɾޡΓ FSSPS  w ܭࢉɼ؍ଌए͘͠͸ଌఆ͞Εͨ஋ຢ͸ঢ়ଶͱɼ ਅͷɼࢦఆ͞Εͨए͘͠͸ཧ࿦తʹਖ਼͍͠஋ ຢ͸ঢ়ଶͱͷؒͷ૬ҧ +*49

     w ܽؕ EFGFDU όάΛؚΉ֓೦  w ҙਤͨ͠ৼΔ෣͍͔ΒγεςϜ͕ҳΕͯ͠· ͏ݪҼͱͳΔιϑτ΢ΣΞγεςϜͷಛੑͰ ͋Δ ΦϒδΣΫτࢦ޲ೖ໳ୈ̎൛ݪଇɾί ϯηϓτܖ໿ϓϩάϥϛϯά  w ো֐ GBVMU ˠ"LLB͸GBVMUUPMFSBODF w ཁٻ͞ΕͨػೳΛ਱ߦ͢Δػೳ୯Ґͷೳྗͷɼ ॖୀຢ͸૕ࣦΛҾ͖ى͜͢ɼҟৗͳঢ়ଶ +*4 9  w ނো GBJMVSF  w ཁٻ͞ΕͨػೳΛ਱ߦ͢Δɼػೳ୯Ґͷ ೳྗ͕ͳ͘ͳΔ͜ͱ +*49 Ұൠతͳ࿈࠯ϑϩʔ ނো ޡࠩɾޡΓ ো֐ ܽؕ ނো
  6. ώΤϥϧΩʔ ଱ো֐ੑ 3FTJMJFOU w ͦΕ͸Ұ౓΋ো֐Λى͜͞ͳ ͍ɺ׬શͳΞϓϦέʔγϣϯ ιϑτ΢ΣΞΛ࣮૷͢Δ͜ͱ Ͱ͸ͳ͍ɻো֐͔Βճ෮͢Δ ͨΊͷೳྗΛσβΠϯ͢Δɻ w

    ϦΞΫςΟϒγεςϜͰ͸ɺ ԼҐͷίϯϙʔωϯτ্ͷεʔ ύόΠβͱର࿩͢Δ͜ͱͰো ֐ʹඋ͑ΔɻεʔύʔόΠβ ͸ɺ؂ಜԼʹ͋Δίϯϙʔω ϯτͷো֐ʹ൓Ԡ͢ΔػձΛ ༩͑ΒΕΔɻ "DUPS 4VQFSWJTPS ো֐ͷൃੜ "DUPS ؂ಜऀͷࢦࣔ ܖ໿ҧ൓࣌͸ΤϥʔΛฦ͢ SFR SFT
  7. ଱ো֐ੑ 3FTJMJFOU w ো֐ൃੜ࣌ʹɺԼҐίϯϙʔ ωϯτΛఀࢭͨ͠Γɺ࠶ىಈ ͨ͠Γɺແࢹͯ͠ܧଓͨ͠Γ Ͱ͖Δɻ·ͨɺ͞Βʹ্Ґͷ εʔύόΠβνΣΠϯʹো֐ ௨஌ΛΤεΧϨʔτ͢Δ͜ͱ ΋Ͱ͖Δɻ

    w ͜ͷΞϓϩʔνͰো֐͕ൃੜ ͨ͠ྖҬΛ෼཭͠ɺଞͷؔ܎ ͠ͳ͍ଟ͘ͷྖҬΛอޢ͢Δ ͜ͱ͕Ͱ͖Δɻ͜ΕΒΛশ͠ ͯࣗݾճ෮ྗͱ͍͏ɻ "DUPS 4VQFSWJTPS ো֐ൃੜ ྫ֎௨஌ 4VQFSWJTPS ྫ֎ͷΤεΧϨʔτ ఀࢭ ࠶ىಈ ܧଓ ఀࢭ ࠶ىಈ ܧଓ "DUPS "DUPS "DUPS "DUPS "DUPS ࠶ىಈ࣌͸ೖସ
  8. ஄ྗੑ &MBTUJD w εέʔϥϏϦςΟʹ͸ɺਨ௚ͱਫ ฏ͕͋ΔɻͲͪΒ͔Ұํ΋͘͠ ͸྆ํಉ࣌ʹ࢖͏͜ͱ͕Ͱ͖Δɻ ஄ྗੑͱ͸ཁٻʹԠͨ͡εέʔ ϦϯάઓུɻΦϑϐʔΫ࣌͸ແବ ʹϦιʔεΛར༻͠ͳ͍ͳͲɻ w

    ϝοηʔδۦಈʹΑͬͯɺίϯ ϙʔωϯτ͸ඞཁʹԠͯ͡ಁա తʹϩʔΧϧϊʔυ΋ϦϞʔτ ϊʔυ΋ར༻Ͱ͖ΔɻҐஔಁա ੑͷ͋ΔίϯϙʔωϯτΛར༻ Ͱ͖Δɻίϯϙʔωϯτͷϝο ηʔδۦಈͱҐஔಁաੑͷ྆ํ Ͱ஄ྗੑΛ࣮ݱ͢Δɻ /PEF DPSF UISFBE DPSF UISFBE DPSF UISFBE DPSF UISFBE "DUPS "DUPS "DUPS "DUPS /PEF "DUPS /PEF "DUPS /PEF "DUPS .FTTBHF CZ"DUPS3FG .FTTBHFCZ"DUPS3FG 4DBMJOHVQ 4DBMJOHPVU 4DBMJOHPVU 4DBMJOHPVU 4DBMJOHPVU 4DBMJOHPVU
  9. ϝοηʔδۦಈ w ϝοηʔδΛड৴ͯ͠ॳΊͯɺར༻ՄೳͳεϨουΛ࢖ͬͯ൓Ԡ͢Δɻϝοηʔδ ʹ൓Ԡ͠ͳ͍ίϯϙʔωϯτ͸وॏͳ$16ࢿݯΛফඅ͠ͳ͍ɻ w ϝοηʔδʹ൓Ԡ͢Δ͔Ͳ͏͔͸ίϯϙʔωϯτ͕બ୒Ͱ͖ɺى͖ಘΔϝοηʔδ ʹඋ͑Δ͜ͱ͕Ͱ͖Δɻ͜ΕʹΑͬͯɺૹ৴ଆͱड৴ଆͷίϯϙʔωϯτ͸ɺΠϯ λʔϑΣΠεͱ͔࣌ؒΒ෼཭͞ΕΔɻ BLLBSFNPUFΛ࢖͏ͱۭؒ΋෼཭Ͱ͖Δ 

    w ϝοηʔδ͸ඇಉظʹૹ৴͞Είϯϙʔωϯτ͸Ұ౓ʹܾ·ͬͨ୯Ґͷϝοηʔδ Λॲཧ͢Δɻ$16Λසൟʹফඅ͢ΔϙʔϦϯάͱϒϩοΩϯάΛ࠾༻ͤͣɺߴε ϧʔϓοτʹϑΥʔΧε͢ΔͨΊʹ$16Λղ์͢ΔɻඞཁʹԠͨ͡൓Ԡ͕௿ϨΠς ϯγʔΛಋ͘ɻ ඞཁʹԠͯ͡όοΫϓϨογϟʹΑΔϑϩʔ੍ޚ΋Մೳ "DUPS "DUPS DMBTT5PEP"HHSFHBUFFYUFOET"DUPS\ PWFSSJEFEFGSFDFJWF3FDFJWF\
 ࠷ޙʹॲཧͨ͠ίϚϯυ*%ΑΓ େ͖͘ͳ͍ͱॲཧ͠ͳ͍ ܖ໿ͷදݱ  DBTFSFR$SFBUF5PEPJGDNEJEMBTU*E Ϩεϙϯε΋ඇಉظʹฦ͞ΕΔ ੒ޭ $SFBUF5PEP4VDDFFEFE Λฦ͢ TFOEFS DSFBUF5PEP SFR  DBTFDNE$SFBUF5PEPJGDNEJEMBTU*E TFOEFS $SFBUF5PEP&SSPS ʜ ΤϥʔΛฦ͢ ^ PWFSSJEFEFGSFDFJWF3FDFJWF\
 DBTFSFRʜ UPEP"HHSFHBUF$SFBUF5PEP ʜ  'JSFBOE'PSHFU ൃՐͨ͠Β͙͢ʹ๨ΕΔ DBTFSFT$SFBUF5PEP4VDDFFEFE Ϩεϙϯε͕͖ͨΒ൓Ԡ͢Δ
 ^
  10. "LLBͱ͸ w IUUQBLLBJP w -JHIUCFOEࣾ$50+POBT#POÉSࢯ͕࠷ॳʹ։ൃɻ w ىݯ͸&SMBOHɻ w ೥$BSM)FXJUUࢯ͕ߟҊ͕ͨ͠ɺ&SMBOHͰ༗໊ʹͳͬͨɻ w

    ಛ௃ w ϦΞΫςΟϒએݴΛαϙʔτ͍ͯ͠Δ w εέʔϧΞοϓ ฒߦ  w εέʔϧΞ΢τ ϦϞʔςΟϯά  w ଱ো֐ੑ w ࠾༻ࣄྫ w ιʔγϟϧϝσΟΞ w σʔλղੳ w ϔϧεέΞ w ౤ࢿ෼໺ ϚʔνϟϯτɾόϯΩϯά  w Ϊϟϯϒϧܥʜɻ
  11. ͳͥ"LLBͳͷ͔  w $16ةػ w γϯάϧίΞةػ ೥ࠒ͔ΒϚϧνίΞొ৔  w ϚϧνίΞ͸୯ҰίΞ͕௿଎ʹͳΔ܏޲ʹ͋ΔͨΊɺΞϓϦ

    έʔγϣϯͷฒߦ౓͕௿͍ͱύϑΥʔϚϯε͕௿Լ͢Δͱ͍ ͏ϦεΫ͕͋Δ ϚϧνίΞةػ ɻ͔͠͠ɺεϨουϓϩά ϥϛϯά͸ɺσουϩοΫ΍ϨʔείϯσΟγϣϯɺՄࢹੑ ͷ໰୊ͳͲͰඇৗʹ೉͍͠ͱ͍͏໰୊͕͋Δɻ w $,໰୊ w ૿͑ଓ͚ΔΫϥΠΞϯτΛͲͷΑ͏ʹॲཧ͢Δ͔ͷ໰୊ɻ໰ ୊ʹͳΔͷ͸ϒϩοΩϯά*0 /HOJY ʙ  /PEFKT ʙ ͸ϊϯϒϩοΩϯά*0ͱΠϕϯτϧʔϓͰ ղܾͨ͠
  12. ͳͥ"LLBͳͷ͔  w ϚϧνίΞةػΛλʔήοτʹͨ͠ݴޠͷొ৔ w &SMBOH 4DBMB ʜ w ෆมੑ΍ܰྔϓϩηεͳͲ

    w &SMBOHͷ఻આ w ೥&SJDTTPO͕ΞΫλʔϞσϧΛϕʔεʹͨ͠&SMBOHΛ։ ൃɻి࿩ަ׵ػͰ OJOFOJOFT࿦ཧతʹ͸ ೥ؒͷՔಇͰඵͷఀࢭ࣌ؒ ɻ೥8IBU"QQ͕୆ͷ αʔόͰສΫϥΠΞϯτΛࡹ͘ɻ w "LLBͷొ৔ w ೥"LLBϦϦʔεɻϝοηʔδۦಈ ϊϯϒϩοΩϯ ά*0Ͱ$,໰୊Λղܾɻ೥ͷهࣄͰ͸&SMBOHͷഒͷ εϧʔϓοτΛൃشͨ͠ͱ͍͏ࣄྫ΋͋Δɻ
  13. "LLBͷओͳϓϩμΫτ  w BLLBBDUPS w ෼ࢄͱฒߦΛ࣮ݱ͢ΔͨΊͷΞΫλʔϞσϧΛఏڙ͢Δɻ؆ ୯ͳ"1*ͰεϨου؅ཧ΍ϩοΫͷऔΓѻ͍Λܰݮɻ w BLLBSFNPUF w

    ϦϞʔτ্ͷϊʔυͰՔಇ͢ΔΞΫλʔʹϝοηʔδύο γϣϯ͢ΔͨΊͷϓϩμΫτɻ w BLLBDMVTUFS w ଱ো֐ੑͷ͋Δ෼ࢄܕ11ϕʔεΫϥελΛߏங͢ΔͨΊͷ ϓϩμΫτɻ w BLLBIUUQ FYQFSJNFOUBM  w )551Λܦ༝ͯ͠"DUPSΛެ։ͨ͠Γɺ"DUPSϕʔεͷ)551 ΫϥΠΞϯταʔϏεΛར༻͢ΔͨΊͷϓϩμΫτ
  14. "LLBͷओͳϓϩμΫτ  w BLLBQFSTJTUFODF w εςʔτϑϧΞΫλʔͷ಺෦ঢ়ଶΛӬଓԽ͢ΔػೳɻΞΫλʔͷॳظ Խ࣌΍ྫ֎ʹΑΔ࠶ىಈ࣌ɺ+7.ͷΫϥογϡ࣌ʹҎલͷঢ়ଶΛ෮ݩ ͢Δ͜ͱ͕Ͱ͖Δɻ w BLLBQFSTJTUFODFRVFSZ

    w ඇಉظετϦʔϜϕʔεͷΫΤϦ*'ʹΑͬͯఏڙ͞ΕΔΫΤϦʔί ϯϙʔωϯτɻ w BLLBTUSFBN w ΞΫλʔΛ࿈݁ͤͯ͞ඇಉظετϦʔϜॲཧΛ͢ΔͨΊͷ1JQFBOE 'JMUFSΛ࡞Δ͜ͱ͕Ͱ͖Δ͕ɺ҆ఆͨ͠ετϦʔϛϯάॲཧΛ͢Δʹ ͸ɺΤϥʔϋϯυϦϯάΛߦͬͨΓɺ͋Δϓϩηε্ͷόοϑΝ΍ ϝʔϧϘοΫε͕Φʔόʔϑϩʔ͠ͳ͍Α͏ʹ͢Δ CBDLQSFTTVSF ඞཁ͕͋Δɻ੩తܕͳཁૉΛѻ͏ετϦʔϜͰΞΫλʔ͸഑ઢϛεΛ ๷ࢭ͢Δ੩తܕ෇͚Λอূ͢Δํ๏͕ͳ͍ɻBLLBTUSFBN͸͜ΕΒͷ ໰୊Λղܾ͢Δɻ
  15. υϝΠϯϞσϧͱ͸ w zυϝΠϯϞσϧͱ͸ಛఆͷਤͰͳ͘ɺ ਤ͕఻͑Α͏ͱ͢Δߟ͑ํͰ͋Δz w ࠨਤ͸ੈلͷதࠃͷੈք஍ਤɻࠃ ಺ʹؔ৺͕͋ΔͨΊɺ֎ࠃ͸͓͟ͳ Γͳදݱɻ w zͲΜͳϞσϧ΋ɺݱ࣮ͷԿΒ͔ͷଆ

    ໘΍ڵຯͷର৅ͱͳΔ֓೦Λද͍ͯ͠ ΔɻϞσϧͱ͸؆ૉԽͰ͋Δɻͭ· Γɺ౰໘ͷ໰୊Λղܾ͢Δ্Ͱؔ࿈ ͢Δଆ໘Λந৅Խ͠ɺͦΕҎ֎ͷৄ ࡉΛແࢹ͢Δ͜ͱʹΑͬͯߦΘΕͨɺ ݱ࣮ʹର͢Δ̍ͭͷղऍͳͷͩɻz
  16. υϝΠϯۦಈઃܭͷҙٛ  w ͜Ε·Ͱ͸ɺϞσϧͱ͸σʔλͷೖΕ෺ͰɺͦΕ Λૢ࡞ͯ͠खଓ͖Λ࣮ݱ͢ΔαʔϏεΛ࣮૷͢ Δɺͱ͍͏ٕज़ۦಈͳߟ͑ํ͕த৺ͩͬͨ τϥϯ βΫγϣϯεΫϦϓτ ɻ w

    υϝΠϯۦಈͰ͸ɺυϝΠϯϞσϧ͕ࣔ͢ߟ͑ํ Λ֩৺ʹ͢Δɻ%%%Ͱ͸͜ͷ੹຿Λ୲͏ΦϒδΣ Ϋτ܈Λڠௐಈ࡞ͤ͞Δ͜ͱΛલఏͱ͍ͯ͠Δɻ
  17. υϝΠϯۦಈઃܭͷҙٛ  w ೥୅ɺ"MBO,BZࢯͷ%ZOBCPPLߏ૝͸ɺzίϯϐϡʔ λ͸ਓؒͷਫ਼ਆ ϝϯλϧϞσϧ Λ֦ுͨ͠΋ͷͰ͋Δz ͱ͍͏ൃ૝͔Βੜ·ΕͨɻޙʹͦΕΛιʔείʔυʹ൓ ө͢ΔͨΊʹΦϒδΣΫτࢦ޲ϓϩάϥϛϯάݴޠ 4NBMMUBMLΛ։ൃɻ

    w ೥ʹ.7$ߟҊऀͷ5SZHWFࢯ͸ɺzϞσϧͱ͸஌ࣝͷ ද৅Ͱ͋Δzͱఏএͨ͠ɻͦ΋ͦ΋ɺ.7$ͷ.ͱ͸σʔ λͰ΋ॲཧΛهड़͢Δ͚ͩͷ΋ͷͰ͸ͳ͘ɺϞσϧ͕ࣔ ͢ߟ͑ํʹ֓೦Λࣔ͢΋ͷͰ͋Δɻ w %%%Ͱ͸ɺϞσϧߟ͑ํͱίʔυΛ݁ͼ͚ͭͨιϑτ ΢ΣΞΛ࣮ݱ͢Δɻݪ఺ճؼͰ΋͋ΓैདྷͷԆ௕ઢ্ʹ ͋Δ΋ͷͰ͋Δɻ
  18. %%%ͰͲ͏มΘΔͷ͔ w ϞϊϦεͳγεςϜ͕ཁ݅ͷมԽͱͱ΋ʹෳࡶԽ͢Δɻ w ڥք෇͚ΒΕͨίϯςΩετ ҎԼ#$ ʹΑͬͯɺۀ຿ʹ߹Θͤ ͯγεςϜΛద੾ʹ෼ׂɾ౷߹͢ΔɻڥքʹΑͬͯ௿݁߹ɾߴڽ ूΛ࣮ݱՄೳ ͋Β͔͡Ί༧ଌͰ͖ͳ͍ͱ͍͏໰୊΋͋Δ

    ɻ w ސ٬ͱ։ൃऀͷѻ͏ݴ༿͕ҟͳΓɺυϝΠϯϞσϧͱιϑτ΢ΣΞ ͷ࣮૷ίʔυʹဃ཭͕ੜ͡Δɻ w ސ٬ͱ։ൃऀͰڞ௨ͷݴޠମܥʢϢϏΩλεݴޠʣΛཱ֬͠ɺͦ ΕʹΑͬͯͰදݱ͞ΕΔυϝΠϯϞσϧΛιϑτ΢ΣΞʹ൓ө͢ Δɻ w τϥϯβΫγϣϯॲཧͱσʔλओମͷzτϥϯβΫγϣϯεΫϦϓ τz͸ɺϩδοΫͷॏෳʹؾ͖ͮʹ͘͘มߋՕॴͷݟۃΊ͕೉͍͠ɻ w ֓೦ͷॏෳ͕ͳ͍υϝΠϯϞσϧΛجʹιϑτ΢ΣΞΛߏங͠ɺ ϏδωεͷมԽʹରԠͰ͖ΔΑ͏ʹඋ͑Δ ͨͩ͠ɺมߋίετ͕ ͳ͍ͱ͍͏༁Ͱ͸ͳ͍ ɻ
  19. #$ͱϚΠΫϩαʔϏε ࢓ೖ#$ ࡏݿ#$ ग़ՙ#$ ൢച#$ ࢓ೖ؅ཧαʔϏε ঎඼ ࢓ೖઌ ࡏݿ؅ཧαʔϏε ঎඼

    อ؅৔ॴ ग़ՙ؅ཧαʔϏε ঎඼ ग़ՙઌ ൢച؅ཧαʔϏε ঎඼ ஫จ ސ٬
  20. Ϟσϧۦಈઃܭͱ͸ w lઃܭ͕͋Δ͍͸ઃܭͷத৺ͱͳΔ෦෼͕ɺυϝΠϯϞσϧ ʹඥ෇͍͍ͯͳ͍ͳΒ͹ɺͦͷϞσϧʹ΄ͱΜͲՁ஋͸ͳ ͘ɺιϑτ΢ΣΞ͕ਖ਼֬Ͱ͋Δ͔Ͳ͏͔΋ٙΘ͍͠ɻಉ͡Α ͏ʹɺϞσϧͱઃܭ͞Εͨػೳͱͷඥ෇͚͕ෳࡶͩͱཧղ͢ Δͷ͕೉͘͠ɺ࣮ࡍʹ͸ɺઃܭ͕มߋ͞Εͨ࣌ʹඥ෇͚Λҡ ࣋Ͱ͖ͳ͘ͳΔɻz w lඥ෇͚͕໌Β͔ʹͳΔΑ͏ʹɺυϝΠϯϞσϧΛจࣈ௨Γ

    ͷҙຯͰ஧࣮ʹ൓өͤ͞Δ͜ͱɻϞσϧʹ͍ͭͯ࠶ݕ౼͠ɺ ΑΓࣗવʹιϑτ΢ΣΞʹ࣮૷͞ΕΔΑ͏ʹमਖ਼͢Δ͜ͱɻ தུίʔυ͸ϞσϧͷදݱͱͳΔ͔Βɺίʔυʹର͢Δ มߋ͸Ϟσϧʹର͢ΔมߋʹͳΔ͔΋͠Εͳ͍ɻͦͷӨڹ͸ɺ ϓϩδΣΫτͷଞͷ׆ಈશମ΁ͱదٓ఻Θ͍͔ͬͯͳ͚Ε͹ ͳΒͳ͍ɻz Ͳ͏͢Δͷ͔
  21. υϝΠϯϞσϧͱίʔυͷඥ෇͚ WBMLBUP6TFS
 WBMBEBDIJ6TFSʜ WBM DIBOOFM BENJOJTUSBUPS  LBUPDSFBUF$IBOOFM  JEJE8PSLFSDSFBUF*E

     UJUMF<1+>5FTU  EFTDSJQUJPO4PNF ։ൃϓϩδΣΫτ  DIBOOFM5ZQF$IBOOFM5ZQF(SPVQ  WBMBEBDIJ.FNCFS BENJOJTUSBUPSDSFBUF.FNCFS DIBOOFM BEBDIJ  WBMNFTTBHFBEBDIJ.FNCFSDSFBUF.FTTBHF  JEJE8PSLFSDSFBUF*E  SPPN*ESPPNJE  VTFS*ELBUPJE  WBMVF͓͔ͭΕ͞·Ͱ͢ WBMDIBOOFM$IBOOFM  JEJE8PSLFSDSFBUF*E  UJUMF<1+>5FTU  EFTDSJQUJPO4PNF ։ൃϓϩδΣΫτ  DIBOOFM5ZQF$IBOOFM5ZQF(SPVQ   WBMLBUP.FNCFS.FNCFS  JEJE8PSLFSDSFBUF*E  SPPN*ESPPNJE  VTFS*ELBUPJE  SPMF5ZQF3PMF5ZQF"ENJOJTUSBUPS  WBMBEBDIJ.FNCFS.FNCFS  JEJE8PSLFSDSFBUF*E  SPPN*ESPPNJE  VTFS*EBEBDIJJE  SPMF5ZQF3PMF5ZQF.FNCFS  WBMNFTTBHF.FTTBHF  JEJE8PSLFSDSFBUF*E  SPPN*ESPPNJE  VTFS*ELBUPJE  WBMVF͓͔ͭΕ͞·Ͱ͢ ශ݂঱ ඇශ݂঱ දݱ๛͔ͳυϝΠϯϞσϧ͔Βɺϝϯόʔ ʹͳΒͳ͍ͱϝοηʔδ͕ૹ৴Ͱ͖ͳ͍ͳͲ ͷɺߟ͑ํ͕ཧղͰ͖ΔΑ͏ʹͳΔɻ
  22. ϨΠϠʔԽΞʔΩςΫνϟ  w %*1ʹΑͬͯɺυϝΠϯ૚ͷಠཱੑΛΑΓߴΊ ͨϨΠΞ΢τ΋͋Δɻ υϝΠϯ૚ ΞϓϦέʔγϣϯ૚ ΠϯϑϥετϥΫνϟ૚ ΠϯλʔϑΣΠε૚ υϝΠϯ૚

    ΞϓϦέʔγϣϯ૚ ΠϯϑϥετϥΫνϟ૚ ΠϯλʔϑΣΠε૚ 3FQPTJUPSZ*NQM BT%BP 3FQPTJUPSZ*' "QQMJDBUJPO4FSWJDF %BP3FDPSE 3FQPTJUPSZ*NQM "QQMJDBUJPO4FSWJDF ू໿ͱ ςʔϒϧදݱ ͷ૬ޓม׵ υϝΠϯ૚Λ ஌͍ͬͯΔͷ Ͱςʔϒϧද ݱʹม׵͢Δ ඞཁ͸ඞͣ͠ ΋ͳ͍ ఻౷తͳϨΠϠʔԽΞʔΩςΫνϟ %*1ݪଇΛద༻ͨ͠ ϨΠϠʔԽΞʔΩςΫνϟ
  23. ू໿ͱ͸ Customer CustomerProfile PostalAddress Pref.Value Contact CustomerConfig w ΤϯςΟςΟͱ஋ΦϒδΣΫτΛू ໿ͷதʹ·ͱΊɺ֤ू໿ͷपғʹڥ

    քΛఆٛ͢Δ͜ͱɻ w ڥքͷ಺෦ʹଘࡏ͢ΔΦϒδΣΫτ ΁ͷΞΫηε͸ͦͷϧʔτΛܦ༝͠ ੍ͯޚ͢Δ͜ͱɻϧʔτ͕ΞΫηε Λ੍ޚ͢ΔͷͰɺ಺෦͕஌Βͳ͍͏ ͪʹมߋ͞ΕΔ͜ͱ͸ͳ͘ͳΔɻ w ͲΜͳঢ়ଶมԽʹ͓͍ͯ΋ɺू໿಺ ʹ͋ΔΦϒδΣΫτͱू໿શମʹର͠ ͯɺෆม৚݅Λ͢΂ͯڧ੍͢Δ͜ͱ ͕ݱ࣮తʹͳΔɻ $VTUPNFS಺෦ͷΦϒδΣΫτ͸ $VTUPNFS͕͔͋ͣΓ஌Β͵ͱ͜ΖͰ ঢ়ଶมԽͯ͠͸ͳΒͳ͍ɻ ඞͣ$VTUPNFSΛ௨ͯ͠ߦ͏
  24. ':*ू໿Λ"DUPSͰ࣮૷͢Δཧ༝ w ू໿ΞΫλʔ಺෦ͷࢀর ʹ௚઀ΞΫηε͢Δ͜ͱ͕ Ͱ͖ͳ͍ɻ w ϝοηʔδΛհͯ͠ͷΈঢ় ଶͷมߋ΍औಘ͕Մೳɻ w ͭ·Γɺू໿ΞΫλʔΛ

    ܦ༝͢Δ͜ͱͰɺඞવతʹ ෆม৚݅Λҡ࣋Ͱ͖ΔΑ ͏ʹͳΔɻ class Counter extends Actor {
 
 var count: Int = 0
 
 override def receive: Receive = {
 case Counter.Increment =>
 count += 2
 case Counter.Get =>
 sender() ! Value(count)
 }
 }
 
 import Counter._
 
 val system = ActorSystem()
 
 val c = system.actorOf(Props[Counter])
 implicit val timeout = Timeout(1 seconds)
 
 // c.count ͦ΋ͦ΋ίϯύΠϧͰ͖ͳ͍
 
 c ! Increment
 val r = (c ? Counter.Get).mapTo[Value] 
 println(r)
  25. "LLBΛجʹͨ͠ϨΠϠʔԽΞʔΩςΫνϟ w ΄΅͢΂͕ͯBLLBBDUPS΋͘͠BLLBTUSFBN͸ϕʔεͱͳΔɻ w ू໿͸੔߹ੑͷ࠷খ୯Ґɻू໿ͷ֎͸݁Ռ੔߹ɻ w 44ͷ৔߹͸ϦϙδτϦ͕ඞཁ͕ͩɺ&4Ͱ͋Ε͹BLLB QFSTJTUFOFDΛ࢖͑͹ϦϙδτϦ͸ෆཁ w Ұ࿈ͷखଓ͖͸ϓϩηεϚωʔδϟͰ࣮ݱɻ

    υϝΠϯ૚ ΞϓϦέʔγϣϯ૚ ΠϯϑϥετϥΫνϟ૚ ΠϯλʔϑΣΠε૚ 3PVUF 31$ 3FR3FT.PEFM 1SPDFTT.BOHFS BT"4 %"0 3FDPSE "HHSFHBUF"DUPS 1SPDFTT .BOBHFS BT%4 &OUJUZ 7BMVF0CKFDU 3FQPTJUPSZ "DUPS
  26. /PEF" $MVTUFS $234 &WFOU4PVSDJOH "HHSFHBUF 4IBSE 4UBUF "HHSFHBUF 4VQFSWJTPS "HHSFHBUF

    4UBUF "HHSFHBUF 4VQFSWJTPS ʜ ʜ &WFOU4UPSF 3FTQPOTF%# /PEF# $MVTUFS /PEF$ /PO$MVTUFS 3FBE.PEFM6QEBUFS 3FBE%BP "QQMJDBUJPO4FSWJDF BT1SPDFTT.BOBHFS 4IBSE3FHJPO $POUSPMMFS"DUJPO 4IBSE$PPSEJOBUPS DMVTUFSTJOHMFUPO 4IBSE 4IBSE3FHJPO "HHSFHBUF 4UBUF "HHSFHBUF 4VQFSWJTPS 4IBSE "HHSFHBUF 4UBUF "HHSFHBUF 4VQFSWJTPS 4IBSE ʜ ʜ "HHSFHBUF 4UBUF "HHSFHBUF 4VQFSWJTPS ʜ 3FBE.PEFM6QEBUFS 3FBE.PEFM6QEBUFS $MVTUFS಺Ͱ"DUPSΛҰ͚ͭͩʹͰ͖Δ 4IBSE಺ʹ"DUPSΛ෼ࢄͰ͖Δ εςʔτϨεͳ4USFBN εςʔτϨεͳ4USFBN "QQMJDBUJPO4FSWJDF $POUSPMMFS"DUJPO
  27. BLLBBDUPSͷྫ class MyActor extends Actor {
 val log = Logging(context.system,

    this)
 
 def receive = {
 case n: Int => log.info("received {}", n)
 case msg: String => sender() ! "***" + msg + "***"
 case _ => log.info("received unknown message")
 }
 }
 
 implicit val system = ActorSystem()
 
 val props1 = Props[MyActor]
 
 val actorRef = system.actorOf(props1)
 
 actorRef ! 1
 
 val future = (actorRef ? "HelloWorld").mapTo[String]
 val result = Await.result(future, Duration.Inf)
 println(result)
 
 actorRef ! 1L 'JSFBOE'PSHFU͸౤͛ͬͺͳ͠ɻϝιο υίʔϧʹ૬౰͢Δϝοηʔδ͸ΞΫλʔ ͕ड͚ೖΕΔ͔Ͳ͏͔ΛܾΊ͍ͯΔɻ໭ Γ஋͸࣌ؒతͳ੍໿͕ͳ͍ɻϝοηʔδ ͸TFOEFSʹฦ౴Λฦ͞ͳ͍XBZͱTFOEFS ʹฦ౴Λฦ͢XBZ͕͋Δɻ
  28. 4VQFSWJTPSΛ࣮૷͢Δ class Supervisor(childProps: Props) extends Actor {
 
 override val

    supervisorStrategy = OneForOneStrategy() {
 case _: NumberFormatException => Restart
 case _: IllegalArgumentException => Stop
 case _: Exception => Escalate
 }
 
 val child = context.actorOf(childProps, "child")
 
 override def receive: Receive = {
 case msg => child forward msg
 }
 }
 4VQFSWJTPS͕ड৴ͨ͠ϝοηʔδ͸ࢠΞΫλʔʹసૹ͢Δɻ TFOEFSΛม͑ͳ͍ɻ
 ਺஋ม׵Ͱ͖ͳ͍৔߹͸3FTUBSU ෆਖ਼ͳೖྗ৚݅ͳΒ&TDBMBUF ͢ΔɺεʔύόΠβετϥςδΛ૊ΈࠐΉɻ4VQFSWJTPS͸ྫ֎ Λड͚औΔͱো֐Λִ཭͢Δɻ
  29. ࢠΞΫλʔΛ࣮૷͢Δ case class ToInt(value: String)
 case class IntValue(value: Int)
 


    class MyActor extends Actor {
 val log = Logging(context.system, this)
 
 @scala.throws[Exception](classOf[Exception])
 override def preStart(): Unit = {
 log.info("child start")
 super.preStart()
 }
 
 def receive = {
 case ToInt(v) =>
 require(v.length > 0)
 sender() ! IntValue(v.toInt)
 case _ =>
 }
 
 @scala.throws[Exception](classOf[Exception])
 override def postStop(): Unit = {
 log.info("child stop")
 super.postStop()
 }
 
 } ࢠΞΫλʔͰ͸جຊతʹྫ֎ΛϋϯυϦ ϯά͠ͳ͍ɻਖ਼ৗܥͷΈͷ࣮૷ͰΑ͍ɻ TFOEFS ͸4VQFSWJTPSͰ͸ͳ͍ΦϦδφ ϧɻ
  30. 4VQFSWJTPSܦ༝Ͱ࣮ߦ͢Δ implicit val system = ActorSystem()
 val childProps = Props[ToIntActor]


    val props = Supervisor.props(childProps)
 
 val toIntActorRef = system.actorOf(props)
 
 Seq("1", "a", "2", "").foreach{ s =>
 try {
 val future = (toIntActorRef ? ToInt(s)).mapTo[IntValue]
 val result = Await.result(future, Duration.Inf)
 println(s"value = $s, result = $result")
 } catch {
 case ex: Exception =>
 ex.printStackTrace()
 }
 } ظ଴͢Δɺظ଴͠ͳ͍ɺೖྗ஋Λ౉ͯ͠ΈΔɻ
  31. [INFO][akka://default/user/$a/child] child start 
 // 1ճ໨͸੒ޭɻ value = 1, result

    = IntValue(1) // 2ճ໨͸ࣦഊɻ࠶ىಈ͕͔͔Δɻ [ERROR][akka://default/user/$a/child] For input string: “a" java.lang.NumberFormatException: For input string: "a" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) [INFO][akka://default/user/$a/child] child stop [INFO][akka://default/user/$a/child] child start akka.pattern.AskTimeoutException: … 
 // 3ճ໨͸੒ޭ value = 2, result = IntValue(2) // 4ճ໨͸ࣦഊɻΞΫλʔ͕ఀࢭ͢Δ [ERROR][akka://default/user/$a/child] requirement failed java.lang.IllegalArgumentException: requirement failed at scala.Predef$.require(Predef.scala:212) [INFO][akka://default/user/$a/child] child stop akka.pattern.AskTimeoutException: … ࣮ߦ݁Ռ "DUPSΠϯελϯε͸࠶ىಈ͕ͨ͠"DUPS3FG͸ͦͷ· ·ར༻Մೳɻ௨ৗͷΦϒδΣΫτࢀরͰ͸ΦϒδΣΫ τάϥϑͷೖΕସ͕͑ߴίετʹͳΔ͜ͱ͕͋Δɻ
  32. ':*εʔύϏδϣϯώΤϥϧΩʔ  w εʔύόΠβͷϥΠϑλΠϜ͸ɺࢠΞΫλʔ ͕ଘࡏ͢Δؒͱಉ͡ɻ਌ʹΑͬͯ࡞ΒΕͨ ࢠΞΫλʔ͸ɺεʔύόΠβͷ؂ಜԼʹ ஔ͔ΕΔɻεʔύόΠβͷ੹೚͸͢΂ͯ ͷࢠΞΫλʔ͕ऴྃͨ࣌͠ʹऴΘΔɻ w Ϋϥογϡ͢ΔՄೳੑ͕ߴ͍ΞΫλʔ͸ɺ

    ՄೳͳݶΓώΤϥϧΩʔͷԼ૚ʹ഑ஔ͢ ΂͖ɻԼ૚Ͱى͖ͨো֐͸ɺ্Ґ·Ͱͷ ώΤϥϧΩʔ͕؅ཧɾΤεΧϨʔγϣϯ ͕Մೳɻ࠷্Ґ͕ো֐Λىͨ͜͠৔߹ ͸ɺ࠷্ҐͷΞΫλʔͷ࠶ىಈ΋͘͠͸ ΞΫλʔγεςϜͷγϟοτμ΢ϯ͕ඞཁ ʹͳΔɻ 4VQFSWJTPS 4VQFSWJTPS 4VQFSWJTPS $IJME $IJME 4VQFSWJTPS $IJME $IJME $IJME $IJME $IJME
  33. ':*εʔύϏδϣϯώΤϥϧΩʔ  w ར఺͸ɺ֤ΞΫλʔ͕௚ ઀௨৴͢Δ͜ͱɻεʔύ όΠβ͸؂ಜۀ຿ͱΠϯ ελϯε࡞੒ͷΈɻ w ܽ఺͸࠶ىಈ͔͠࢖͑ͳ ͍͜ͱͱɺࢠΞΫλʔ͕

    ఀࢭ͍ͯ͠Δࡍ͸ϝοηʔ δ͕σουϨλʔʹૹΒ ΕࣦͯΘΕͯ͠·͏͜ ͱɻ਌ͷ؂ಜ͸ϝοηʔ δϑϩʔ͔Β؂ಜΛ෼཭ ͯ͠͠·͏ɻ -PH'JMF8BUIDFS 4VQFSWJTPS -PH1SPDDFTTPS 4VQFSWJTPS 3PX -PH'JMF /FX'JMF %BUBCBTF -PH1SPDDFTTPS %C8SJUFS -PH'JMF8BUIDFS %C8SJUFS 4VQFSWJTPS ώΤϥϧΩʔͷҧ͏-PH1SPDDFTTPSͷ "DUPS3FGΛಘΔͷ͸೉͍͠
  34. ':*εʔύϏδϣϯώΤϥϧΩʔ  w εʔύόΠβ͸୯ͳΔੜ੒ ΍؂ಜ͚ͩͰ͸ͳ͘ɺؒ઀ ࢀরͱͯ͠ɺ͢΂ͯͷϝο ηʔδΛ୯ʹಁաతʹϑΥ ϫʔυ͢ΔɻεʔύόΠβ ͸֎෦ͷΞΫλʔͱ͸ແؔ ܎ʹɺ಺෦ͷࢠΞΫλʔΛ

    ऴྃͨ͠Γɺ৽͍͠΋ͷΛ ੜΈग़ͨ͠ΓͰ͖Δɻ w ઌͷྫͱൺ΂ͯϝοηʔδ ϑϩʔͷΪϟοϓ͕ͳ͍ɻ -PH'JMF8BUIDFS4VQFSWJTPS -PH1SPDDFTTPS4VQFSWJTPS 3PX -PH'JMF /FX'JMF %BUBCBTF -PH1SPDDFTTPS %C8SJUFS -PH'JMF8BUIDFS %C8SJUFS4VQFSWJTPS
  35. %PNBJO&WFOU DNESFRSFT 1FSTJTUFOU"DUPSͰ࣮૷͢Δू໿ΞΫλʔ w෭࡞༻Λى͜͢ͱυϝΠϯΠϕϯτ͕ӬଓԽ͓ΑͼൃՐ͞ΕΔ 5PEP "HHSFHBUF "DUPS $MJFOU"DUPS $SFBUF3FRVFTU 6QEBUF5FYU3FRVFTU

    %FTUSPZ3FRVFTU (FU4UBUF3FRVFTU $SFBUF3FTQPOTF 6QEBUF5FYU3FTQPOTF %FTUSPZ3FTQPOTF (FU4UBUF3FTQPOTF 5PEP$SFBUFE 5PEP/BNF6QEBUFE 5PEP%FTUSPZFE TVCTDSJCFS ෭࡞༻͕ى͖ΔίϚϯυ͕डཧ͞Εͨ৔ ߹͸υϝΠϯΠϕϯτ͕ൃՐ͞ΕΔ BLLBQFSTJTUFODF KPVSOBMT TOBQTIPUT KPVSOBM KPVSOBM KPVSOBM TOBQTIPU TOBQTIPU TOBQTIPU υϝΠϯΠϕϯτͱε ςʔτΛӬଓԽ͢Δ
  36. ू໿ΞΫλʔ class TodoAggregate(id: TodoId, subscriber: Option[ActorRef])
 extends PersistentActor {
 private

    var state: Option[Todo] = None
 private var eventCounter = 0L
 override def persistenceId: String = TodoAggregate.name(id)
 
 override def receiveCommand: Receive = {
 case Create(requestId, aggregateId, todoGroupId, text) =>
 require(aggregateId == id)
 val now = ZonedDateTime.now()
 state = Some(Todo(id, todoGroupId, text, now, now))
 persist(Created(UUID.randomUUID(), aggregateId,
 todoGroupId, text, now, now)
 ) { event =>
 sender() ! CreateSuccess(UUID.randomUUID(), requestId,
 aggregateId, todoGroupId, text, now, now)
 subscriber.foreach(_ ! event)
 saveSnapshotEntity()
 }
 case Update(requestId, aggregateId, text) =>
 require(aggregateId == id)
 val now = ZonedDateTime.now()
 state.map(_.copy(text = text, updateAt = now))
 persist(Updated(UUID.randomUUID(),
 aggregateId, text, now)
 ) { event =>
 sender() ! UpdateSuccess(UUID.randomUUID(),
 requestId, aggregateId, text, now)
 subscriber.foreach(_ ! event)
 saveSnapshotEntity()
 } ɹঢ়ଶΛ࣋ͭ ӬଓԽ*% ίϚϯυϋϯυϥ ΠϕϯτΛӬଓԽ͢Δ ඞཁʹԠͯ͡ εφοϓγϣοτ Λ࡞੒ TFOEFS ʹ ϨεϙϯεΛฦ͢ 4VCTDSJCFSʹ υϝΠϯΠϕϯτΛ ௨஌
  37. case Delete(requestId, aggregateId) =>
 require(aggregateId == id)
 val now =

    ZonedDateTime.now()
 state = None
 persist(Deleted(UUID.randomUUID(), aggregateId, now)) { event =>
 sender() ! DeleteSuccess(UUID.randomUUID(), requestId, aggregateId, now)
 subscriber.foreach(_ ! event)
 saveSnapshotEntity()
 context.stop(self)
 }
 case Get(requestId, aggregateId) =>
 require(aggregateId == id)
 val response = state.map { e =>
 GetSuccess(UUID.randomUUID(), requestId, aggregateId, e)
 }.getOrElse {
 GetError(UUID.randomUUID(), requestId, aggregateId, new EnityNotFoundException())
 }
 sender() ! response
 } override def receiveRecover: Receive = {
 case env: Created =>
 require(env.aggregateId == id)
 state = Some(Todo(env.aggregateId, env.todoGroupId, env.text,
 env.createAt, env.updateAt))
 case env: Updated =>
 require(env.aggregateId == id)
 state.map(_.copy(text = env.text, updateAt = env.updateAt))
 case Deleted(_, aggregateId, updateAt) =>
 require(aggregateId == id)
 state = None
 context.stop(self)
 case SnapshotOffer(metadata, snapshot: Todo) =>
 state = Some(snapshot)
 }
 // …
 } ঢ়ଶΛϦΧόϦ͢Δϋϯυϥ ঢ়ଶΛฦ͢ εφοϓγϣοτΛऔಘͨ͠Β ঢ়ଶΛߋ৽͢Δ
  38. %PNBJO&WFOU DNESFRSFT 1FSTJTUFOU'4.Ͱ࣮૷͢ΔϓϩηεϚωʔδϟ wड৴ͨ͠Πϕϯτ͸ӬଓԽ͞ΕΔɻ w4UBUFঢ়ଶʹԠͨ͡%BUB΋εφοϓγϣοτͱͯ͠ӬଓԽͰ͖Δɻ 3FHJTUSBUJPO1SPDFTT.BOBHFS $MJFOU"DUPS $SFBUF3FRVFTU $SFBUF3FTQPOTF 5PEP$SFBUFE

    5PEP/BNF6QEBUFE 5PEP%FTUSPZFE BLLBQFSTJTUFODF KPVSOBMT TOBQTIPUT KPVSOBM KPVSOBM KPVSOBM TOBQTIPU TOBQTIPU TOBQTIPU 5PEP(SPVQ"HHSFHBUF 5PEP"HHSFHBUF 4UBUF 4UBSUFE 5PEP(SPVQ$SFBUJOH 5PEP$SFBUJOH 4VDDFFEFEc'BJMFE %BUB 3FHJTUSBUJPO%BUB
  39. class RegistrationProcessManager(id: UUID, todoGroupRef: ActorRef, todoRef: ActorRef) (implicit val domainEventClassTag:

    ClassTag[RegistrationEvent])
 extends PersistentFSM[State, RegistrationData, RegistrationEvent] { 
 override def persistenceId: String = RegistrationProcessManager.name(id)
 override def applyEvent( domainEvent: RegistrationEvent, currentData: RegistrationData): RegistrationData = {
 domainEvent match {
 case TodoGroupCreatingStarted(cmd, sender) =>
 currentData.copy(sender = Some(sender), todoReq = Some(cmd.todo), todoGroupReq = Some(cmd.todoGroup))
 case TodoGroupCreatingFinished(res) =>
 currentData.copy(todoGroupRes = Some(res))
 case TodoCreatingFinished(res) =>
 currentData.copy(todoRes = Some(res))
 }
 }
 startWith(Started, RegistrationData.empty)
 when(Started) {
 case Event(req: CreateTodoWithTodoGroupRequest, _) =>
 val _sender = sender()
 goto(TodoGroupCreating) applying TodoGroupCreatingStarted(req, _sender) forMax 1.seconds andThen { _ =>
 self ! req.todoGroup
 }
 }
 ϓϩηεϚωʔδϟ υϝΠϯΠϕϯτϋϯυϥ ঢ়ଶͷॳظԽ $SFBUF5PEP8JUI5PEP(SPVPQ3FRVFTUΛड͚औΔͱ 5PEP(SPVQ$SFBUJOHʹભҠͨ͠ޙʹɺ 5PEP(SPVQ$SFBUJOH4UBSUFEͱ͍͏υϝΠϯΠϕϯτΛൃՐ͠ 5PEP(SPVQΛ࡞੒͢ΔίϚϯυΛൃՐ͢Δ
  40. when(TodoGroupCreating) {
 case Event(req: TodoGroupProtocol.Create, _) =>
 stay forMax 3.seconds

    andThen { _ => todoGroupRef ! req }
 case Event(res: TodoGroupProtocol.CreateSuccess, _) =>
 goto(TodoCreating) applying TodoGroupCreatingSucceeded(res) forMax 1.seconds andThen {
 case RegistrationData(_, _, Some(req), _, _) =>
 saveStateSnapshot(); self ! req
 }
 case Event(res: TodoGroupProtocol.CreateError, _) =>
 goto(TodoCreating) applying TodoGroupCreatingFailed(res) forMax 1.seconds andThen {
 case RegistrationData(Some(sender), _, _, _, _) =>
 sender ! CreateTodoWithTodoGroupResponse(res, None)
 }
 } when(TodoCreating) {
 case Event(req: TodoProtocol.Create, _) =>
 stay forMax 3.seconds andThen { _ => todoRef ! req }
 case Event(res: TodoProtocol.CreateSuccess, _) =>
 goto(Succeeded) applying TodoCreatingSucceeded(res) 
 forMax 1.seconds andThen { _ => self ! Done }
 case Event(res: TodoProtocol.CreateError, _) =>
 goto(Failed) applying TodoCreatingFailed(res)
 forMax 1.seconds
 }
 when(Succeeded) {
 case Event(Done, RegistrationData( Some(sender), _, _, Some(todoGroupRes), todoRes)) =>
 sender ! CreateTodoWithTodoGroupResponse( todoGroupRes, todoRes)
 stop()
 } when(Failed) {
 case Event(Done, RegistrationData( Some(sender), _, _, Some(todoGroupRes), todoRes)) =>
 sender ! CreateTodoWithTodoGroupResponse(todoGroupRes, todoRes)
 stop()
 }
 } 5PEP(SPVQ"DUPSʹίϚϯυΛൃՐ Ϩεϙϯε͕੒ޭͨ͠৔߹͸5PEPΛ࡞੒͢Δঢ়ଶ ʹભҠ͢Δɻ Τϥʔͷ৔߹͸TFOEFSʹΤϥʔΛ௨஌͢Δ தؒঢ়ଶΛӬଓԽ͢Δ 5PEP"DUPSʹίϚϯυΛൃՐ Ϩεϙϯε͕੒ޭͨ͠৔߹͸'JOJTIFEʹભҠ͢ Δɻ Τϥʔͷ৔߹͸TFOEFSʹΤϥʔΛ௨஌͢Δɻ ͢΂ͯ੒ޭͨ͠ΒTFOEFSʹϨεϙϯεΛฦ͢ɻ
  41. object Main
 extends Appɹwith TodoWriteService with TodoReadService with TodoGroupWriteService
 with

    TodoGroupReadService {
 
 private implicit val system = ActorSystem("akka-ddd-sample")
 override protected implicit val materializer = ActorMaterializer()
 private implicit val executionContext = system.dispatcher
 
 private val profileProvider = ProfileProvider("datasource")
 private val todoDao = new TodoDao(profileProvider)
 private val todoGroupDao = new TodoGroupDao(profileProvider)
 override protected val todoDas = new TodoDas(todoDao)
 override protected val todoGroupDas: TodoGroupDas = new TodoGroupDas(todoGroupDao)
 
 override protected val todoAggregateRef: ActorRef =
 system.actorOf(TodoSupervisor.props(TodoAggregate.props))
 override protected val todoGroupAggregateRef: ActorRef =
 system.actorOf(TodoGroupSupervisor.props(TodoGroupAggregate.props))
 
 private val route: Route = todoWriteRoute ~ todoReadRoute ~ todoGroupWriteRoute ~ todoGRoupReadRoute
 private val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
 
 sys.addShutdownHook {
 bindingFuture
 .map(_.unbind)
 .onComplete(_ => system.terminate())
 }
 
 } BLLBIUUQCJOE"OE)BOEMF αʔόͷىಈ
  42. trait TodoWriteService extends Directives {
 private implicit val timeout =

    Timeout(10 seconds)
 protected val todoAggregateRef: ActorRef
 val todoWriteRoute: Route = createTodo ~ updateTodo ~ deleteTodo
 
 private val createTodo: Route = {
 path("todos") {
 post {
 entity(as[CreateTodoRequestJson]) { requestBody =>
 val commandId = UUID.randomUUID()
 val todoId = TodoId(UUID.randomUUID())
 val todoGroupId = TodoGroupId(UUID.randomUUID())
 val future = (todoAggregateRef ? Create(commandId, todoId, todoGroupId, requestBody.text))
 .mapTo[CreateSuccess]
 onSuccess(future) { res =>
 complete(CreateTodoResponseJson(res.id, res.aggregateId.value))
 }
 }
 }
 }
 } // …
 } BLLBIUUQ3PVUF
  43. trait TodoReadService extends Directives {
 protected implicit val materializer: Materializer


    protected val todoDas: TodoDas
 protected val todoReadRoute: Route = getTodoById ~ getTodos
 
 private val getTodoById: Route = {
 pathPrefix("todos" / JavaUUID) { id =>
 get {
 val future = todoDas.findById(TodoId(id)).runWith(Sink.head)
 onSuccess(future) { res =>
 complete(GetTodoResponseJson(res.id.value, res.text, res.createAt, res.updateAt))
 }
 }
 }
 }
 
 private val getTodos: Route = {
 path("todos") {
 get {
 val future = todoDas.findAll
 .map { e => GetTodoResponseJson(e.id.value, e.text, e.createAt, e.updateAt) }
 .runWith (Sink.seq)
 onSuccess(future) { res =>
 complete(GetTodosResponseJson(res))
 }
 }
 }
 }
 
 }
  44. ·ͱΊ  w ϒϩοΩϯάϕʔεͷίʔυΑΓෳࡶԽ͍ͯ͠Δ͕ɺ ੜͰεϨου΍ϊϯϒϩοΩϯά"1*΍Πϕϯτϧʔ ϓΛࣗલͰ࣮૷͢ΔΑΓந৅Խ͞Εͨίʔυͱͳͬͯ ͍Δɻߴ͍ඇػೳཁ͕݅໰ΘΕΔ৔߹͸ҰߟͷՁ஋͕ ͋ΔͷͰ͸ͳ͍͔ɻ w ϦΞΫςΟϒγεςϜ͸·ͩᴈ໌ظͳͷͰɺϑϨʔϜ

    ϫʔΫ΍ಋೖࣄྫ͕ॆ࣮͍ͯ͠ͳ͍ 4QSJOH3FBDUPS ʹ͸4VQFSWJTJPO͕ͳ͍ɻ"LLBʹ͸ҰԠ+BWB"1*͕͋ Δ ɻ·͡Ίʹ΍ΔͳΒ4DBMB"LLB͔&SMBOH051͙ Β͍͔͠૝૾Ͱ͖ͳ͍ɻࠓͷ͏ͪʹ४උΛͯ͠มԽʹ ରԠͰ͖Δํ͕Α͍ͷͰ͸ͳ͍͔ɻ
  45. ·ͱΊ  w ঺հ͍͚ͨ͠ͲͰ͖ͳ͔ͬͨτϐοΫ w BLLBTUSFBN w BLLBDMVTUFS BLLBDMVTUFSTIBSEJOH w

    %JTUSJCVUFE1VC4VC w #BDLP⒎4VQFSWJTPS $JSDVJU#SFBLFS w ˞ڵຯ͕͋Ε͹ௐ΂ͯΈ͍ͯͩ͘͞ w ڵຯ͕͋Δਓ͸ҎԼͷຊΛಡΈ·͠ΐ͏ɻ