2018/06/06 に開催された「Unity テスト完全に理解した」という勉強会での発表資料です。
גࣜձࣾΩοζελʔ CTOɹ࠸ͯ͞ີ݁߹ͩͳΦϝʔClean Architecture ͰֶͿςετϑϨϯυϦʔͳૄ݁߹ઃܭUnity ςετશʹཧղͨ͠ @ 2018/06/06
View Slide
2͜ΜΜʂ
3ಥવͰ͕͢ઃܭਤͷݕূ༻ઃܭਤςετɺॻ͍ͯ·͔͢ʁ
4ࢲɺ࠷ۙ·Ͱॻ͍͍ͯ·ͤΜͰͨͬ͠ʂ
rΜΓ͌ઌੜl͋ͳͨͨͪͷதͰςετΛॻ͍͍ͯΔऀ͕ɺ·ͣɺࢲʹੴΛ͛ͳ͍͞ɻz5
6͋͋ͬʂੴΛ͛ͳ͍ͰʂϚαΧϦΛ͛ͳ͍Ͱʂʂʢ࣮ʣ
ࣗݾհ7
wɹ࠸ʢBLBΜΓ͌ઌੜʣw࡛ۄݝ࢈wגࣜձࣾΩοζελʔ$50wࡀϲ݄ͷ່ʹκοίϯ-07&w͓ञͱ߹এͱϓϩάϥϛϯά͕झຯw5XJUUFS!NPOSZ(JU)VC!NPOSZ8Who am I ?
w ࢠͲ͚εϚϗΞϓϦ ։ൃͳͲw ͋ͨΓ͔Β 6OJUZΨοπϦw ͬ͜͝ϥϯυ ྦྷܭສ%-w "QQ4UPSF(PPHMF1MBZ ʹͯࢠͲ͚ΧςΰϦ ϥϯΩϯά5019͓͠͝ͱ
લஔ͖10
11ࠓճ
12ϓϩδΣΫτͷίʔυΛςετ͠қ͘͢Δख๏ʹ͍͓ͭͯ͠͠·͢ɻ
ΞδΣϯμ13
w6OJUZςετʹ͓͚Δ՝wૄ݁߹ͷجຊతͳߟ͑ํw$MFBO"SDIJUFDUVSFʹ͍ͭͯw$"'6ʹ͍ͭͯ14͓͠ͳ͕͖
15ຊ
w6OJUZςετʹ͓͚Δ՝wૄ݁߹ͷجຊతͳߟ͑ํw$MFBO"SDIJUFDUVSFʹ͍ͭͯw$"'6ʹ͍ͭͯ16͓͠ͳ͕͖
Unity ςετʹ͓͚Δ՝17
w୯ମςετ6OJU5FTUw݁߹ςετ*OUFHSBUJPO5FTUw૯߹ςετ4ZTUFN5FTU18ςετ is ԿʁUnity ςετʹ͓͚Δ՝
wʮ͍ɺγϯϓϧͳΫϥεͳΒ65ॻ͚ΔΜ͢Αʯwঢ়ଶΛඞཁͱ͢Δςετ͕γϯυΠw֎෦σʔλʹґଘ͢Δςετɺ4DSJQUBCMF0CKFDUͷσʔλʹґଘ͢Δςετ͕ γϯυΠw7JFX .POP#FIBWJPVSʹґଘ͢Δͱ͔ͳΔͱ ઈత19Կނɺॻ(͔|͚)ͳ͍ʁUnity ςετʹ͓͚Δ՝
wʮ͍ɺ1MBZ.PEFςετ͋ΔΜʯw͍ͬͯ͟ΈΔͱɺ৭ʑͳ՝͕ ݟ͑ͯ͘Δ20Կނɺॻ(͔|͚)ͳ͍ʁUnity ςετʹ͓͚Δ՝
w͋ΔΫϥεͭҎ্ͷΫϥεͷ ΠϯελϯεΛඞཁͱ͍ͯ͠Δw߹ʹΑͬͯɺͦΕΒͷ ΠϯελϯεߋʹผͷΫϥεͷ ΠϯελϯεΛඞཁͱ͍ͯ͠Δ ͳΜͯ͜ͱ21՝ʁUnity ςετʹ͓͚Δ՝
wσʔλͷݩωλʹڌΒͣɺσʔλΛ औಘɾઃఆ͢ΔॲཧΛςετ͍ͨ͠w<0CTPMFUF>3FTPVSDFT-PBE w6OJUZ8FC3FRVFTUwϩʔΧϧΩϟογϡwFUD22՝ʁUnity ςετʹ͓͚Δ՝
w7JFXͷॲཧ͕λοϓೖྗΛલఏʹ͍ͯ͠Δwଞͷ(BNF0CKFDU͕ॳظԽ͞Ε͍ͯΔίτΛલఏʹ͍ͯ͠Δw4JOHMFUPOͱ͔ͰલͷγʔϯͰઃఆ͞ΕͨΛඞཁͱ͢Δ23՝ʁUnity ςετʹ͓͚Δ՝
24͜͏͍͏ঢ়ଶ
25is
26ີ݁߹
27ີ݁߹
28ີ݁߹
29
w4JOHMFUPO.POP#FIBWJPVSűŒŕŰŖwTUBUJD͓͡͞Μw ߦΛ͑Δ6QEBUF 30ີ݁߹Unity ςετʹ͓͚Δ՝
wͪΐͬͱؾΛൈ͘ͱ͙͢͜͏ͳΔw݁߹Λ΄Ͳ͍ͯૄ݁߹ʹ͠Α͏ʂ31ີ݁߹Unity ςετʹ͓͚Δ՝
32ͦͷลΛ౿·͑ͯ
w6OJUZςετʹ͓͚Δ՝wૄ݁߹ͷجຊతͳߟ͑ํw$MFBO"SDIJUFDUVSFʹ͍ͭͯw$"'6ʹ͍ͭͯ33͓͠ͳ͕͖
ૄ݁߹ͷجຊతͳߟ͑ํ34
35
36Ҏ্ɻ
37………ɻ
38ૄ݁߹ͷͨΊͷ ςΫχοΫΛʢࡶʹʣհ
w4JOHMF3FTQPOTJCJMJUZ1SJODJQMFw0QFODMPTFEQSJODJQMFw-JTLPWTVCTUJUVUJPOQSJODJQMFw*OUFSGBDFTFHSFHBUJPOQSJODJQMFw%FQFOEFODZJOWFSTJPOQSJODJQMF39SOLID ݪଇૄ݁߹ͷجຊతͳߟ͑ํ
w୯Ұͷݪଇw։์ดͷݪଇwϦείϑͷஔݪଇwΠϯλϑΣʔεͷݪଇwґଘੑٯసͷ๏ଇ40SOLID ݪଇૄ݁߹ͷجຊతͳߟ͑ํ
41
w40-*%ݪଇ͕कΒΕ͍ͯΔίʔυ ͦͷҰͭҰͭʹ͍ͭͯɺؔ৺ͷ͕ ߦΘΕ͍ͯΔͱݴ͑Δw͢ͳΘͪɺݸʑͷίʔυʹ͓͚Δ ςετରͷؔ৺ࣄ͕গͳ͍w͢ͳΘͪɺૄ݁߹ͩͱݴ͑Δ42SOLID ݪଇૄ݁߹ͷجຊతͳߟ͑ํ
wૄ݁߹ͳγεςϜʹର͢Δςετ ͭͷςετίʔυ͕ෛ͏͕ڱ͍wςετΛ࣮ࢪ͢Δࡍͷ४උॲཧ͕ গͳ͘ͳΔέʔε͕ଟ͍43ૄ݁߹ × ςετૄ݁߹ͷجຊతͳߟ͑ํ
wۃͱͯ͠ɺ֤ཁૉʹର͢Δ65͕ ॻ͔Ε͍ͯΕ*5ͦ͜·Ͱ ؤுΒͳͯ͘ࡁΉ44ૄ݁߹ × ςετૄ݁߹ͷجຊతͳߟ͑ํ
45ͰʁHow to ૄ݁߹ʁ
w6OJUZςετʹ͓͚Δ՝wૄ݁߹ͷجຊతͳߟ͑ํw$MFBO"SDIJUFDUVSFʹ͍ͭͯw$"'6ʹ͍ͭͯ46͓͠ͳ͕͖
Clean Architecture ʹ͍ͭͯ47
48ͷɺલʹ
w͜͜·Ͱ୯ҰͷΫϥεʹؔ͢Δ ؔ৺ͷʹ͍ͭͯwҰͭࢹ࠲Λ֦͛ͯϨΠϠʔʹؔ͢Δ ؔ৺ͷʹ͍ͭͯߟ͑Δ49ؔ৺ͷClean Architecture ʹ͍ͭͯ
wιϑτΣΞΞʔΩςΫνϟʹԙ͍ͯɺҰൠʹҎԼͷ Α͏ʹϨΠϠʔΛ͚Δ ʢίτ͕ଟ͍ʣw1SFTFOUBUJPO ݟͨw%PNBJO ϩδοΫw%BUB σʔλ50ؔ৺ͷ for ϨΠϠʔPresentationDomainDataClean Architecture ʹ͍ͭͯ
w.7$.71ͳͲͷ ΞʔΩςΫνϟʹΑΓ 1SFTFOUBUJPOͱ%PNBJO ͷ͕࣮ݱ͞ΕΔw֤ΞʔΩςΫνϟͰ ͷ۩ମతͳखஈ ༷ʑw.71.77.ͩͱ 3YΛ͏ͷ͕Ұൠతʁ51ؔ৺ͷ for ϨΠϠʔPresentationDomainDataClean Architecture ʹ͍ͭͯ
w%PNBJOͱ%BUBͷ ֤छσβΠϯύλʔϯ͕ ୲͏͜ͱ͕ଟ͔ͬͨwͱ͍͏͔ɺ.7Ͱ %PNBJOҎ߱ʹ͍ͭͯͷ ΛΞʔΩςΫνϟ ͱͯ͠ෛ͍ͬͯͳ͍ײ͡52ؔ৺ͷ for ϨΠϠʔPresentationDomainDataClean Architecture ʹ͍ͭͯ
wͰɺͦͷลఆٛͨ͠ ΞʔΩςΫνϟ͕ొ͢Δw)FYBHPOBM"SDIJUFDUVSFw0OJPO"SDIJUFDUVSFw$MFBO"SDIJUFDUVSF53ؔ৺ͷ for ϨΠϠʔPresentationDomainDataClean Architecture ʹ͍ͭͯ
54Α͏͘ຊ
w6ODMF#PC 3PCFSU$.BSUJOࢯ͕݄ʹఏҊwJ04ͷ7*1&3ͳΜ͔ίϨ͕ݯྲྀ55Clean ArchitectureClean Architecture ʹ͍ͭͯ
56Clean ArchitectureClean Architecture ʹ͍ͭͯ
57ͳΔ΄ͲɺΘ͔ΒΜɻ
58ࢲͳΓʹղऍͯ͠Έͨ
wϨΠϠʔͷׂΛఆٛ͢ΔwϨΠϠͷΛ໌֬ԽwOBNFTQBDFͳͲͰ ͔Γ͘͢͢Δ59Clean ArchitectureClean Architecture ʹ͍ͭͯ
wґଘͷϧʔϧΛकΔwؔ৺ͷ͖ҰํwݪଇతʹಉϨΠϠʔؒ ґଘͤ͞ͳ͍wϨΠϠʔΛඈͼӽ͑ͳ͍60Clean ArchitectureClean Architecture ʹ͍ͭͯ
wϨΠϠʔఆٛࣗ༝wͱ͔ෆఆwϓϩμΫτຖʹॊೈʹwΓͳ͖Ό૿͢61Clean ArchitectureClean Architecture ʹ͍ͭͯ
wϨΠϠʔؒͷؔ৺Λw40-*%ݪଇwJOUFSGBDFΛ༻͍ͯ ۩Ϋϥεͷґଘഉআw%FQFOEFODZ*OKFDUJPOT62Clean ArchitectureClean Architecture ʹ͍ͭͯ
wಉ৺ԁͷਤؔ৺ͷ͖wଆ֎ଆΛΒͳ͍w(BUFXBZT%#͕ Ͳ͏ͬͯσʔλΛ ѻ͏͔Βͳ͍ɺͱ͔wσʔλͷྲྀΕผͷ͓wӈԼͷਤ͕ιϨ63Clean ArchitectureClean Architecture ʹ͍ͭͯ
64ΜͰ
65͜ΕΛ Unity ʢ͔ͬͯ C#ʣ Ͱ࣮ͯ͠Έͨ
w6OJUZςετʹ͓͚Δ՝wૄ݁߹ͷجຊతͳߟ͑ํw$MFBO"SDIJUFDUVSFʹ͍ͭͯw$"'6ʹ͍ͭͯ66͓͠ͳ͕͖
CAFU ʹ͍ͭͯ67
w$MFBO"SDIJUFDUVSF'PS6OJUZͷུwʮ͔;ʔʯͱಡΉwώωϦ͕ͳ͍ͱ͔ݴΘͳ͍ɻw.*5-JDFOTFͳ044[email protected]68CAFU is ԿʁCAFU ʹ͍ͭͯ
wجຊతʹJOUFSGBDFͷΈΛఏڙw6OJUZͱର͢Δ্ͰඞཁʹͳΔ ΫϥεΛఏڙwΩοζελʔͷΞϓϦ։ൃͰ ઈͬͯΔ69CAFU is ԿʁCAFU ʹ͍ͭͯ
70ϨΠϠʔఆٛ
71ϨΠϠʔఆٛCAFU ʹ͍ͭͯ
72ґଘؔCAFU ʹ͍ͭͯ
w.POP#FIBWJPVSͱର͠ ݟͨΛ࢘ΔϨΠϠʔw1SFTFOUFSͷΈґଘՄ73Presentation / ViewCAFU ʹ͍ͭͯ
w7JFXͱ6TF$BTFΛܨ͙ϨΠϠʔw6TF$BTFޙड़wঢ়ଶΛ࣋ͨͳ͍74Presentation / PresenterCAFU ʹ͍ͭͯ
wϏδωεϩδοΫͷ࣮ͦͷͷwܭࢉॲཧͳͲΛ୲͏wޙड़ͷ.PEFMͱͯ͠දݱ͞ΕΔ ঢ়ଶΛอ࣋ͨ͠Γ͢Δ75Domain / UseCaseCAFU ʹ͍ͭͯ
wओʹ7JFXͰͷར༻Λతͱͨ͠ σʔλͷߏw6OJ3YΛ௨ͯ͡7JFXʹૹΒΕΔw3YετϦʔϜΛؚΊͨঢ়ଶΛཧ76Domain / ModelCAFU ʹ͍ͭͯ
wޙड़ͷ&OUJUZͱ.PEFMͱΛ૬ޓม͢ΔͨΊͷTranslate()ϝιουΛ උ͑Δw֎෦༷ͷมߋΛ6TF$BTF7JFXʹͤ͞ͳ͍ͨΊʹఆٛ77Domain / TranslatorCAFU ʹ͍ͭͯ
w%BUBϨΠϠʔͱର͢ΔͨΊͷ ϨΠϠʔwσʔλΛಡΈॻ͖͢ΔͨΊͷ ΠϯλϑΣʔεΛ࣋ͭ78Domain / RepositoryCAFU ʹ͍ͭͯ
wσʔλͷߏΛఆٛͨ͠ϨΠϠʔwσʔλͷ࣮ମ͕ԿͰ͋Εɺ ߏදݱͱͯ͠ҰͭͷΫϥεͰද͢w4DSJQUBCMF0CKFDU͕ϝϯυΠʜɻ79Data / EntityCAFU ʹ͍ͭͯ
wσʔλͷऔΓѻ͍Λ࣮ͨ͠ϨΠϠʔw4DSJQUBCMF0CKFDUͱ͔ɺ 8FC"1*ܦ༝ͷ+40/ͱ͔ɺ 42-JUFܦ༝ͷσʔλͱ͔ɺFUD80Data / DataStoreCAFU ʹ͍ͭͯ
wFOVNͱ͔DPOTUతͳΛཧ͢ΔͨΊͷ"QQMJDBUJPOϨΠϠʔw%*༻ͷ'BDUPSZΫϥεͱ͔Λ ֨ೲ͢Δ6UJMJUZϨΠϠʔ81ͦͷଞCAFU ʹ͍ͭͯ
wམͪϞϊήʔϜΛྫʹղઆwʙ৭ͷάϛ͕ ݸηοτͰམԼwͭἧ͏ͱফ͑Δwළͷ࠷্ஈ·Ͱୡͨ͠Β ήʔϜΦʔόʔwͦͷ࣌ͷείΞΛه82ྫ͑CAFU ʹ͍ͭͯ
• Controllerw γʔϯ੍ޚw 1SFTFOUFSॳظԽ• Gummiw ߱ͬͯ͘Δάϛ •FloorwϘτϧͷচ•CeilwϘτϧͷఱҪ•WallwϘτϧͷน83Presentation / ViewCAFU ʹ͍ͭͯ
w Gummiʹ.PDLΠϕϯτ͕ඈΜͰ͖ͨΒ .PDL1SFTFOUFSͷϝιου͕ݺΕΔ͔ʁςετw .PDL1SFTFOUFSͷ3YετϦʔϜʹ ͕ྲྀΕ͖ͯͨΒWall͕ΤϑΣΫτΛ *OTUBOUJBUF͢Δ͔ʁςετ84Presentation / ViewCAFU ʹ͍ͭͯ
•StagePresenterwγʔϯैଐ1SFTFOUFS85Presentation / PresenterCAFU ʹ͍ͭͯ
86Presentation / PresenterCAFU ʹ͍ͭͯw StagePresenterͷ֤ϝιουΛςετw 6TF$BTFͷΠϯελϯεશͯ.PDLw 1SFTFOUFSϨΠϠʔςετॻ͘ՁΊ
•GummiStateUseCasewεςʔδதͷάϛͷঢ়ଶΛཧɾܭࢉwάϛணˠ࠶ܭࢉͱ͔wͪ͗Εఆͱ͔•ScoreUseCasewಘΛཧɾܭࢉ•StageUseCasewεςʔδͷߏΛཧwԿ৭ͷάϛΛग़͢ʁwམԼεϐʔυʁ87Domain / UseCaseCAFU ʹ͍ͭͯ
88Domain / UseCaseCAFU ʹ͍ͭͯw ֤6TF$BTFͷQVCMJDϝιουΛςετw ೖྗग़ྗ1SJNJUJWFͳJOUFSGBDFΛ ௨ͯ͡ߦΘΕΔϋζw ScoreUseCaseͷ&OUJUZ.PEFM.PDL͢Δ
•GummiModelwάϛҰͭΛදݱw৭ͱ͔4UBUFͱ͔•GummiMapModelwεςʔδͷશάϛใ •ForecastGummiModelw༧ࠂάϛͷঢ়ଶ•ScoreModelwݱࡏͷಘ•PointModelwάϛফڈʹΑΔ֫ಘಘ89Domain / ModelCAFU ʹ͍ͭͯ
90Domain / ModelCAFU ʹ͍ͭͯw ͪΐͬͱͨ͠ͷՃॲཧͳͲΛߦ͍ͬͯΔ ߹ςετॻ͘w جຊతʹςετॻ͔ͳͯ͘Ϥαι
•GummiTranslatorw4UBHF-FWFM&OUJUZͱ Ґஔ͔Β4DPSF.PEFMΛੜ•ScoreEntityTranslatorw4DPSF.PEFMΛ4DPSF&OUJUZʹม91Domain / TranslatorCAFU ʹ͍ͭͯ
92Domain / TranslatorCAFU ʹ͍ͭͯw GummiModelTranslatorIStageLevelEntityΛ .PDLͯ͠Translate()Λςετw ScoreEntityTranslatorIScoreModelΛ .PDLͯ͠Translate()Λςετ
•ScoreRepositorywείΞΛಡΈॻ͖•StageLevelRepositorywεςʔδͷάϛ৭ߏ ͳͲͷϚελΛऔಘ93Domain / RepositoryCAFU ʹ͍ͭͯ
94Domain / RepositoryCAFU ʹ͍ͭͯw ScoreRepositoryIScoreModelͷ.PDLͰςετw StageLevelRepositoryIStageLevelEntity Ͱςετ
•ScoreEntitywεςʔδͷείΞ•ScoreMapEntitywશεςʔδͷείΞ •GummiPointMapEntityw࿈ຖͷ֫ಘϚελ•StageLevelEntitywεςʔδқఆٛ•StageLevelMapEntitywશεςʔδͷқ95Data / EntityCAFU ʹ͍ͭͯ
96Data / EntityCAFU ʹ͍ͭͯw .PEFMಉ༷ɺಛघͳϝιουΛੜ͍ͯ͠ͳ͍ ݶΓςετෆཁ
•ScriptableObjectDataStorewγʔϯதͷҙͷ ίϯϙʔωϯτ͔Β ࢀর͞ΕΔ4DSJQUBCMF0CKFDU͔Β &OUJUZΛऔಘ •LocalStorageDataStorewϩʔΧϧετϨʔδʹ +40/ͱ͔Ͱ&OUJUZΛ อଘͨ͠ΓಡΜͩΓ97Data / DataStoreCAFU ʹ͍ͭͯ
98Data / DataStoreCAFU ʹ͍ͭͯw ScriptableObjectDataStore'JYUVSFγʔϯ ͔ΒͷΠϯελϯεऔಘΛςετw LocalStorageDataStoreҙͷ&OUJUZΛ ૬ޓʹಡΈॻ͖ग़དྷΔ͔Λςετ
99σʔλͷྲྀΕ
wϘλϯ͕ΫϦοΫ͞ΕͯԿ͔ॲཧ͢Δ100σʔλͷྲྀΕCAFU ʹ͍ͭͯ
wԿΒ͔ͷτϦΨʔͰঢ়ଶ͕มԽ101σʔλͷྲྀΕCAFU ʹ͍ͭͯ
wλΠϚʔతͳ࣮102σʔλͷྲྀΕCAFU ʹ͍ͭͯ
wόφʔը૾Λαʔό͔Βऔಘ103σʔλͷྲྀΕCAFU ʹ͍ͭͯ
wόφʔը૾ΛʹΩϟογϡ104σʔλͷྲྀΕCAFU ʹ͍ͭͯ
wϚελσʔλΛ4DSJQUBCMF0CKFDU͔Βऔಘ105σʔλͷྲྀΕCAFU ʹ͍ͭͯ
wϚελσʔλΛ4DSJQUBCMF0CKFDU͔Βऔಘ ʢϥΠτ൛ʣ106σʔλͷྲྀΕCAFU ʹ͍ͭͯ
·ͱΊ107
wૄ݁߹ͳΞϓϦέʔγϣϯΛ ߏங͢Δͱςετ͕͘͢͠ͳΔw$MFBO"SDIJUFDUVSF͕Φεεϝw$"'6ͬͯΈͯͶʂελʔśūŢŒţ108·ͱΊ
109Thank you for yourattention!!