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

リアクティブDDD

かとじゅん
September 29, 2016

 リアクティブDDD

かとじゅん

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 ڵຯ͕͋Δਓ͸ҎԼͷຊΛಡΈ·͠ΐ͏ɻ