Share
Embed
DDD + Clean Architecture + UCDOM Full版
http://ddd-cqrs-es.connpass.com/event/27181/
「Reactive Messaging Patternsプレ読書会 - CQRS、ESの基本を学ぶ -」の時間の都合上カットした部分も含めたフル版資料です。
Embeddedなままだと各種リンクが有効ではないので、気になる方は"Download PDF"よりご参照ください。
Essence版はコチラ:https://speakerdeck.com/yoskhdia/ddd-plus-clean-architecture-plus-ucdom-essenceban
Yoshitaka Okuda
March 20, 2016
Transcript
100 slides
-
About me • ԞాՂڗʢYoshitaka Okudaʣ • גࣜձࣾSocketʢKDDI Syn.ϗʔϧσΟϯάεάϧʔϓʣ ΞʔΩςΫτ •
Twitter @yoskhdia • interested in DDD/Scala/C#/Reactive System/ Architect/System Thinking/Team Building/ Agile/ܦӦใֶ/On-Road Bike -
Agenda • υϝΠϯۦಈઃܭʢDDDʣ͓͞Β͍ • Clean ArchitectureͱԿ͔ • DDD + Clean
Architectureମݧஊ • Ϣʔεέʔεۦಈ։ൃʢICONIXϓϩηεʣʹ ग़ձͬͨ -
ཹҙࣄ߲ • ͜ͷൃදࢲݸਓͷݟղʹدΔͷͰ͢ɻ • ॻ੶ʮυϝΠϯۦಈઃܭʯਖ਼ࣜʹʮΤϦοΫɾΤϰΝϯ εͷʯͱ͘Α͏ʹɺDDDϕετϓϥΫςΟεΛ·ͱΊͨ ࣝମܥͰ͋Γɺઈରͷਖ਼ղͷ͋ΔͷͰ͋Γ·ͤΜɻ • ࠾༻͢ΔϓϩμΫτͷੑ֨ʹΑͬͯɺ۩ମతͳํ๏มΘΓ ·͢ɻʢࠓճUIΛ࣋ͨͳ͍APIͰߟ͍͑ͯ·͢ɻʣ
• ͦͷͨΊɺ͜͏͍͏෩ʹద༻͍ͯ͠Δਓ͍ΔΜͩͳɺͱ͍ ͏Թ͔͍৺Ͱ͓ئ͍͍ͨ͠·͢... -
ͬ͘͟ΓDDD • DDDݴ༿Λେʹ͢Δ։ൃख๏ • ΤΫετϦʔϜϓϩάϥϛϯάʢXPʣΛϕʔεʹϞσϧۦಈઃܭΞϓ ϩʔνΛద༻͍ͯ͠Δ • ϏδωεมԽʹͲ͏ରԠ͍͔͕ͯ͘͠ςʔϚ • ͦͷͨΊʹదԠܕͷϓϩηεͱϞσϧۦಈઃܭΛ͏
• ʢݸਓతʹࢥ͏ͷʣνʔϜͷڌΓॴͱͳΓಘΔ • ໎ͬͨΒಡΉ • νʔϜͷڞ௨ཧղͷݩʹͳΔˠΦϨ༷։ൃख๏͔Βͷ٫ -
ݴ༿ͷఆٛʢݪଇʣ • υϝΠϯʢDomainʣ • ϏδωεશମͷྖҬͦͷͷͷ͜ͱɻιϑτΣΞͰղܾ͢Δͷɺ͜ͷҰ෦ɻ • υϝΠϯϞσϧʢDomain Modelʣ • υϝΠϯʹରͯ͠ɺͦͷղܾࡦʢιϦϡʔγϣϯʣΛϞσϧԽͨ͠ͷɻ
• υϝΠϯΤΩεύʔτʢDomain Expertʣ • υϝΠϯʹਫ਼௨͍ͯ͠ΔਓɻҰਓͰ͋Δ͜ͱ͋ΕෳਓͰ͋Δ͜ͱ͋Δɻ • ίΞυϝΠϯʢCore Domainʣ • υϝΠϯ͍͔ͭ͘ͷྖҬʹׂ͢Δ͜ͱ͕ଟ͍ɻ͜ͷ࣌ɺҰ൪ϏδωεՁͷߴ͍ྖ ҬΛίΞυϝΠϯͱ͍͏ɻ࣌ؒਓ༗ݶͳͷͰίΞυϝΠϯΛݟ͚ͭͯɺͦ͜ʹྗ ͢Δ͜ͱ͕ॏཁɻ -
ݴ༿ͷఆٛʢݪଇʣ • ϢϏΩλεݴޠʢUbiquitous Languageʣ • ίʔυΛॻ͍͍ͯΔͱΦϨΦϨ໋໊Λ͕ͪ͠ɻ͢ΔͱɺυϝΠϯΤΩεύʔτ ͱΛ͢Δͱ͖ʹݴ༿ͷ༁͕ൃੜ͢Δɻ͜͏ͳΔͱɺυϝΠϯΤΩεύʔτ ͷඳ͘Ϟσϧͱίʔυ͕ဃ͍ͯͬͯ͠͠·͏ͷͰɺυϝΠϯΤΩεύʔτΛ ؚΉνʔϜશମͰಉ͡ݴ༿Λ͏Α͏ʹ߹ҙ͢Δɻ •
ڥք͚ͮΒΕͨίϯςΩετʢBounded Contextʣ • จ຺ʢίϯςΩετʣʹΑͬͯɺಉ͡ݴ༿ͳͷʹҟͳΔҙຯʹͳΔ͜ͱ͕͋Δɻ υϝΠϯϞσϧେ͖͘ͳΓ͕ͪͳͷͰɺҰ؏ੑΛอͬͨ··εέʔϧ͢Δʹ ɺίϯςΩετͷڥքΛϋοΩϦͤͯ͞ҙຯͷมΘΒͳ͍ॴΛ࡞Δɻίϯ ςΩετϚοϓͱ͍͏πʔϧΛͬͨΓ͢Δɻ InfoQʮίϯςΩετϚοϐϯάʹΑΔઓུతυϝΠϯۦಈઃܭʯΛࢀর -
υϝΠϯͱίϯςΩετͷؔ υϝΠϯ ίϯςΩετ αϒυϝΠϯ ίΞυϝΠϯ • ઢɿ υϝΠϯڥք • ࣮ઢɿ
ίϯςΩετڥք • ίϯςΩετ͍ ͔ͭ͘ͷυϝΠϯ ڥքʹލΔ͜ͱ͕ ͋Δ • ཧαϒυϝΠ ϯͱίϯςΩετ ͕1ର1 αϒυϝΠϯ -
ݴ༿ͷఆٛʢ࣮ફʣ • ΤϯςΟςΟʢEntityʣ • ʢޡղΛڪΕͣʹݴ͑ʣҰൠʹ૾͢ΔϞσϧͷجຊ୯ҐɻϥΠϑαΠΫϧ ͕͋Δɻ • ूʢAggregateʣ • ͍͔ͭ͘ͷΤϯςΟςΟؒͰ߹ੑΛอͨͳ͚ΕϞσϧͱཱͯ͠͠ͳ͍
߹ʢྫ͑ɺจͱจ໌ࡉʣ͕͋Δɻ͜ΕΒͷΤϯςΟςΟΛଋͶͨͱ͖ɺ ͦͷϧʔτʹҐஔ͢ΔΤϯςΟςΟΛूͱݺͿɻ • ΦϒδΣΫτʢValue Objectʣ • ϥΠϑαΠΫϧແ͘ෆมͷΦϒδΣΫτɻϢϏΩλεݴޠͰఆٛ͞Εͨݴ༿ ͱৼΔ͍Λ࣋ͭ͜ͱͰυϝΠϯϞσϧ͕๛͔ʹͳΔɻ -
ݴ༿ͷఆٛʢ࣮ફʣ • υϝΠϯαʔϏεʢDomain Serviceʣ • ෳͷΤϯςΟςΟʹ·͕ͨΔৼΔ͍ͳͲɺΤϯςΟςΟ͕࣋ͭʹద͞ ͳ͍ৼΔ͍Λఆٛͨ͠υϝΠϯΦϒδΣΫτɻঢ়ଶΛ͍͚࣋ͬͯͳ͍ɻ • ϑΝΫτϦʢFactoryʣ •
ෳࡶͳΦϒδΣΫτAggregateΛੜ͢ΔͨΊͷ࣮ύλʔϯɻΤϯςΟ ςΟͷϥΠϑαΠΫϧͷىʹͳΔɻ • ϦϙδτϦʢRepositoryʣ • ΤϯςΟςΟͷϥΠϑαΠΫϧʹ్͓͍ͯதʢঢ়ଶͷ෮ݩʣͱ࠷ޙʢআʣ Λ୲͏࣮ύλʔϯɻAggregateʹରͯ͠ͷΈ༻ҙ͢Δɻ -
ଞͷΞʔΩςΫνϟ • ϨΠϠʔυΞʔΩςΫνϟ • UIˠΞϓϦέʔγϣϯˠυϝΠ ϯ • Πϯϑϥશͯʹґଘ͞ΕΔ • DDDຊͰݴٴ
• IDDDຊͰΠϯϑϥΛ࠷্Ґʹస ˠΠϯϑϥͷ֎෦ԽΛਐΊΔͱɺ࣍ ߲Ҏ߱ͷΞʔΩςΫνϟʹͭͳ͕Δ -
ଞͷΞʔΩςΫνϟ • ϔΩαΰφϧΞʔΩςΫνϟ • Ports & AdaptersΞʔΩςΫνϟ ͱݴ͏ • த৺ʹApplicationΛஔ͖ɺΠϯϑ
ϥʢUIɺDBɺetcʣΛ֎ଆʹஔ ͘ɻ྆ऀʹPortͱݺΕΔޱ͕ ͋ΓɺAdapterʹΑͬͯଓ͞Ε Δɻ • IDDDຊͰݴٴ -
ଞͷΞʔΩςΫνϟ • ΦχΦϯΞʔΩςΫνϟ • ϔΩαΰφϧͱಉ͡ͰΠϯϑϥ Λ֎෦Խ͍ͯ͠Δ • ϔΩαΰφϧͱͷҧ͍ • ApplicationΛԽ
• ͷґଘํଆ͔͏ • ७ਮʹϨΠϠʔυͷΠϯϑϥ Λ֎ʹ͖࣋ͬͯͨײ͡ -
Clean Architecture֓ཁ • ԁঢ়ͷɺιϑτΣΞͷҟͳΔྖҬΛද͢ • த৺ʹ͍͘΄ͲɺϏδωεՁͷߴ͍ͷΛஔ͘ • ֎ଆͷԁϝΧχζϜɻଆͷԁϙϦγʔɻ • ґଘؔنଇ͕؊
• ࣗΑΓଆͷ͚ͩʹґଘ͢Δ͜ͱ ˠ ֎ଆͷʹ͍ͭͯશ͘ԿΒͳͯ͘ྑ͍ • σʔλܗࣜಉ༷ʹ֎ଆͷͷϑΥʔϚοτΛଆʹ࣋ͪࠐ·ͳ͍ʢྫ͑ɺ JSONΛ࣋ͪࠐ·ͳ͍ɺDBͷRowΦϒδΣΫτΛ࣋ͪࠐ·ͳ͍ʣ • ଆͷಠཱੑʢநʣΛߴΊͯɺ֎ଆͷަΛ༰қʹ͢Δ -
HexagonalOnionͱૂ͍ಉ͡ • ϑϨʔϜϫʔΫ͔Βಠཱ͢Δ ㅟ ㅟ ㅟ ㅟ ΞʔΩςΫνϟϥΠϒϥϦͷଘࡏʹґଘ͠ͳ͍ɻϑϨʔϜϫʔΫͱ͍͏੍ʹγεςϜΛ ٧ΊࠐΉͷͰͳ͘ɺγεςϜʹϑϨʔϜϫʔΫΛͯΊΔɻ •
UI͔Βಠཱ͢Δ ㅟ ㅟ ㅟ ㅟ UIɺγεςϜͷΓͷ෦Λมߋ͢Δ͜ͱͳ͘ɺ༰қʹมߋ͢Δ͜ͱ͕Ͱ͖Δɻྫ͑ Web UI͔ΒίϯιʔϧUIͱஔ͖͑Δ͜ͱ͕Ͱ͖Δɻ • σʔλϕʔε͔Βಠཱ͢Δ ㅟ ㅟ ㅟ ㅟ Oracle·ͨSQL ServerɺMongoBigTableͱ͍ͬͨNoSQLؚΊɺަΛ༰қʹ͢Δɻ ϏδωεϧʔϧɺσʔλϕʔεʹؚΊͳ͍ɻ • ҙͷ֎෦ϦιʔεɺαʔϏε͔Βಠཱ͢Δ ㅟ ㅟ ㅟ ㅟ Ϗδωεϧʔϧɺ୯७ʹ֎ͷੈքʹ͍ͭͯԿΔඞཁͳ͘ɺΓ͍ͨ͜ͱ͚ͩʹ ूத͢Εྑ͍ɻ -
Clean Architectureͷརʁ • ϔΩαΰφϧʴΦχΦϯɺͦΕͧΕͷ͍͍ͱ͜औΓ͕Clean Architecture • ΞϓϦέʔγϣϯʹΛ༩͑ΠϯϑϥͱΞμϓλͰܨ͙ • ґଘؔنଇ͕໌ࣔ͞Ε͍ͯΔ͜ͱ •
୯७ʹਤΛݟ͔ͯΓ͍͢ • Adapter͕ଓΛ୲ͬͯɺ֎ͱܨ͕ΕΔͷUseCaseʹݶఆ • ͷڥքҧDIPͰࢭ • ࢦͯ͠ΔͷͲΕಉ͡ͳͷͰɺνʔϜͰཧղΛಘΒΕ͍͢ͷΛ ͑OK -
Entities(=Domain) • ϨΠϠʔυΞʔΩςΫνϟͰ͍͏υϝΠϯ • اۀશମͷϏδωεϧʔϧΛΧϓηϧԽ • ϝιουΛ࣋ͭΦϒδΣΫτɺ͋Δ͍ɺσʔλߏͱػೳͷηοτ • DDDຊʹ༷ʑͳύλʔϯऩ •
اۀͷ༷ʑͳΞϓϦέʔγϣϯʹΑͬͯ͘ΘΕΔ • ಛఆͷΞϓϦέʔγϣϯͷӡ༻ͷมߋʢྫ͑ɺϖʔδφϏήʔγϣϯη ΩϡϦςΟʣͷӨڹΛΤϯςΟςΟʹ༩͑Δ͖Ͱͳ͍ • اۀΛލ͕ͳ͍୯ҰͷΞϓϦέʔγϣϯΛॻ͍͍ͯΔ߹ͩͱɺΤϯςΟ ςΟΞϓϦέʔγϣϯͱີʹ݁Ε͕ͪɻ -
Use Cases • ϨΠϠʔυΞʔΩςΫνϟͰ͍͏ΞϓϦέʔγϣϯʢαʔϏεʣ • ΞϓϦέʔγϣϯݻ༗ͷϏδωεϧʔϧΛΧϓηϧԽ • γεςϜͷϢʔεέʔεΛ࣮͢ΔɻυϝΠϯͷσʔλͷྲྀΕ Λௐ͠ɺ·ͨɺυϝΠϯΦϒδΣΫτࢦࣔΛग़͢ɻ •
͜ͷͷมߋ͕υϝΠϯʹӨڹͨ͠ΓɺDBUIͷΑ͏ͳ֎෦ ͷมߋʹΑͬͯӨڹΛड͚ͳ͍Α͏ʹ͢Δ͜ͱ͕େࣄɻ • ͔͠͠ɺΞϓϦέʔγϣϯૢ࡞ʹมߋ͕͋Δ߹ɺ͜ͷӨڹ Λड͚ΔɻϢʔεέʔεͷৄࡉΛมߋ͢ΔͳΒɺ͜ͷͷҰ෦ͷ ίʔυ࣮֬ʹӨڹΛड͚Δ͜ͱʹͳΔɻ -
Interface Adapters (Controllers/Presenters/Gateways) • ϑϨʔϜϫʔΫͳͲΛ͍ɺ۩ମతͳϝΧχζϜΛ࣮͢Δ • ͱ֎ͱͷσʔλʢϑΥʔϚοτʣͷม͕ओͳׂ • Controllerɿ ֎͔Βड͚औͬͨσʔλΛͰղऍͰ͖ΔσʔλʢυϝΠϯ
ΦϒδΣΫτʣʹม͢Δɻྫ͑ɺϑΥʔϜϦΫΤετΛυϝΠϯΦϒδΣ Ϋτʹม • Presenterɿ ͔Β͑ΒΕͨσʔλΛ֎Ͱ༻͢Δܗʹม͢Δɻྫ͑ ɺυϝΠϯΦϒδΣΫτΛJSONʹม • GatewayʢDB֎෦αʔϏεʣɿ ʹ۩ମతͳΓऔΓʹؔ͢Δίʔυ ஔ͔ͳ͍Α͏ʹ͢Δɻྫ͑ɺRDBΛ͏࣌ɺSQLͷఆٛ͜ͷʹݶఆ͢Δ -
Frameworks & Drivers (Web/UI/DB/ExternalInterfaces) • ࠷֎ଆͷɺσʔλϕʔεWebϑϨʔϜϫʔΫͳͲ ͷπʔϧͰߏ͞ΕΔɻ • ͜ͷʹ͢Δଆͷͭͳ͛ΔͨΊͷάϧʔίʔυ Ҏ্ͷͷॻ͔ͳ͍ɻ
• WebUIɺσʔλϕʔεͷΑ͏ͳ۩ମతͳ࣮ٕज़ʹɺ গͳ͔Β͕ͣ͋Δɻ • มԽ͕ܹ͍͠෦Ͱ͋ΔͷͰɺ࠷֎ଆʹஔ͍ͯަ Λ༰қʹ͓ͯ͘͜͠ͱ͕υϝΠϯΛकΔ͜ͱʹܨ͕Δɻ -
ઃܭͷϙΠϯτɿڥքͷԣஅ • ԁͷํʹ͕ߦ͖͕͚ͪͩΕͲɺઃܭͷ͏ ͑Ͱ͕ͬͪ͜ॏཁ • ௨ৗɺController͔Βೖ͖ͬͯͯPresenter ʹग़ͯߦ͘ྲྀΕ • UseCase֎ΛΒͳ͍ͷͰɺग़ྗΛฦ ͢ʹґଘؔٯసͷݪଇΛ͍ͬͯΔ
ʢDependency Inversion Principleʣ • ͷڥքΛอͪͳ͕ΒॲཧϑϩʔΛ࣮ݱ ৄࡉޙ΄Ͳ -
·ͱΊ • ඇৗʹγϯϓϧͳϧʔϧͳͷͰ͔Γ͍͢ • Ͱ • େͳͷΛଆʹஔ͘ • ґଘؔنଇʢଆʹͷΈґଘʣΛकΔ •
ಠཱੑςετͷ༰қੑʹߩݙ͢Δ • ٕज़͕ݹ͘ͳͬͨΒ࠷খݶͷखؒͰަͰ͖Δ • ϑϨʔϜϫʔΫΛަ͢Δ͜ͱ͋ͬͯɺυϝΠϯࣝΛަ ͢Δͱ͍͏ͷ͋Γಘͳ͍ -
ύοέʔδߏ • Domain(Entities) • Contract • Domainͱͷڮ͠ ʢDIΛ͏ͷͰΠϯλϑΣʔεผʹ͍ͯ͠Δʣ • UseCase
• Adapter • Repositoryͷ࣮Ϋϥε͜͜ • ʢExternalʣ • ϑϨʔϜϫʔΫϥΠϒϥϦͷͱ͍͏Ґஔ͚ͮ ̐Ͱͳͯ͘0, -
Domain(Entities) • POSO(Plain Old Scala Object)͕جຊ • ϑϨʔϜϫʔΫͷґଘ͚ͩͰͳ͘ɺϥΠϒ ϥϦͷґଘۃྗগͳ͘ •
ࠓͷͱ͜ΖJoda-TimeͷΈʢJava8 Date and Time APIͷҠߦݕ౼தʣ -
Use Case import scala.concurrent.{ExecutionContext, Future} trait UseCase { type
In type Out protected def call(arg: In)(implicit ec: ExecutionContext): Future[Out] } "EBQUFSͱͷ࿈ܞ1PSUʹҕৡ -
Input PortʢPushܕʣ import scala.concurrent.ExecutionContext import scala.util.{Failure, Success} trait PushPort[Arg, Result]
{ self: UseCase => override final type In = Arg override final type Out = Result def execute[T <: Callback[Result]](arg: Arg)(callback: T) (implicit ec: ExecutionContext): Unit = { call(arg).onComplete { case Success(result) => callback.onSuccess(result) case Failure(t) => callback.onFailure(t) } } } "EBQUFS͔ΒͲ͏͏͔ ԿΛฦ͔͢Λఆٛ *OQVU1PSUͷׂ ड͚औΔ͜ͱ·ͰͳͷͰ 6OJUΛฦ͢ -
Output Port trait Callback[Result] { def onSuccess(result: Result): Unit
def onFailure(t: Throwable): Unit } ΞϓϦέʔγϣϯϩδοΫͷΤϥʔ ಛผͳ&YDFQUJPOΛ༻ҙͯ͠ฦ͢Α͏ʹ͍ͯ͠Δ ʢ+BWBͷ׳शʹ͍ۙʣ -
Callback vs Promise(Future) • ScalaʹPromise(Future)͕͋Δ • ࢀߟɿhttps://gist.github.com/okapies/5354929 ※هࣄʹର͢Δίϝϯτ(Togetter)·ͰಡΈ·͠ΐ͏ • ϨϕϧͳCallbackͷํ͕ಋೖোน͕͍
• ߴϨϕϧͳPromiseΛ͍͍ͨͳΒɺCallbackͷ্ ʹඃͤΔܗͰ࣮͢Δ͜ͱ͕Ͱ͖Δ -
Callbackͷ্ʹ PromiseΛࡌͤΔ private class CallbackImpl extends PickedLeaderCallback { val promise
= Promise[UserId]() override def onSuccess(userId: UserId): Unit = { promise.success(userId) } override def onFailure(throwable: Throwable): Unit = { promise.failure(throwable) } } -
Use Caseͷఆٛ package contract.usecase import contract.{PushPort, UseCase} import domain.{GroupId,
UserId} trait PickLeaderUseCase extends UseCase with PushPort[GroupId, UserId] ࣮αϘ͍ͬͯΔ 6TF$BTFͰѻ͍͍͢ ΦϒδΣΫτ %50 ʹ͢Δ -
Use Caseͷ࣮ package usecase import javax.inject.Inject import contract.usecase.PickLeaderUseCase import
domain.UserRepository import scala.concurrent.{ExecutionContext, Future} class PickLeaderUseCaseImpl @Inject()(userRepository: UserRepository) extends PickLeaderUseCase { override protected def call(groupId: In) (implicit ec: ExecutionContext): Future[Out] = { userRepository.findBy(groupId).map { board => board.pickLeader // ୭ΛͲ͏Ϧʔμʹ͢Δ͔υϝΠϯࣝ } } } ΠϯλϑΣʔεΛ͏ %*ͰґଘΛ୯ํʹ -
Controller import contract.usecase.PickLeaderUseCase import domain.GroupId import play.api.data._ import play.api.libs.concurrent.Execution.Implicits.defaultContext import
play.api.mvc.{Action, Controller} class GroupController @Inject() (useCase: PickLeaderUseCase, presenter: PickedLeaderPresenter) extends Controller { val form: Form[GroupId] = ??? // ׂѪ def pickLeader = Action.async { implicit request => form.bindFromRequest.fold(_ => Future.successful(BadRequest("…")), (groupId: GroupId) => presenter.response(useCase.execute(groupId)) ) } } ೖྗσʔλ͔Βͷม͕ ͜ͷॻ͖ํʹ͍ͭͯޙ΄Ͳ -
Presenter import contract.callback.PickedLeaderCallback import domain.UserId import play.api.libs.json.Json import scala.concurrent.{ExecutionContext, Future,
Promise} class PickedLeaderPresenter extends Presenter[PickedLeaderCallback] { implicit val writer = Json.writes[UserId] override def response(call: UseCaseExecutor) (implicit ec: ExecutionContext): Future[Rendered] = { val callback = new CallbackImpl call(callback) callback.promise.future.map { userId => Ok(Json.toJson(userId)) } } } ग़ྗσʔλͷม͕ -
ControllerͰPresenterͷׂΛ ݉ͯ͠ྑ͍ͷͰʁ • ࠓճͷΑ͏ͳখنͳͷͩͱɺͻͱͭͷΫϥεʹશ෦ॻ ͍ͯ͠·͍ͨ͘ͳΔ • ׂͷҟͳΔͷΛҰͭͷΫϥεʹೖΕΔͷ୯Ұ ͷݪଇʹ͢Δ • ControllerೖྗͷมɺPresenterग़ྗͷมʹઐ೦
͢Δ͜ͱͰංେԽ͕͛Δʢίʔυ͢Δʣ • ҰํͰίϯτϩʔϥΛׂ͢Δٕज़ʹ ઃܭʹ͓͍ͯԿΛੋͱ͢Δ͔ɺ͚ͩ -
PresenterΛUseCaseʹ ͯ͠ྑ͍ͷͰʁ • UseCase͔Β݁ՌΛฦ͢͜ͱʹͳΔ • UseCaseҎԼʹPresenterͷΠϯλϑΣʔεʢ͘͠Ϩεϙϯ εͷܕʣ͕ඞཁʹͳͬͯ͠·͏ɻͦΕɺUseCase͕֎ଆͷ ͷׂ͍݉ͯ͠Δ͜ͱʹͳͬͯ͠·͏ͷͰ·͘͠ͳ͍ • ୯ҰͷݪଇͱΑΓɺͱܾͯ͠ΊΒΕׂͨʹઐ೦ͯ͠
ΛแΜͰ͍͘͜ͱͰɺଆͷಠཱੑ্͕͕Δ ʹ֎ଆͷަ༰қੑ্͕͕Δ OK: presenter.response(useCase.execute(groupId)) NG: useCase.execute(groupId)(presenter.response) -
ͦͷଞ • GuiceͷΑ͏ͳDIίϯςφΛ͏ͷ͔ɺScalaͷݴޠػೳΛ ͬͯίϯύΠϧ࣌DIΛ͢Δͷ͔ࣗ༝ • DIίϯςφ࣮͕͋ΔͷͰɺແཧͯ͠ίϯύΠϧ࣌DI ʹ͢Δඞཁແ͍ͱࢥ͍·͢ɻྫ͑ɺScalaΑΓJava ͷํ͕͔Δϝϯόʔ͕ଟ͍ͳΒૉʹDIίϯςφ͍ ·͠ΐ͏ɻ •
ࠓճύοέʔδͰΛ͍ͯ͠·͕͢ɺϚϧνϓϩδΣ ΫτͰ͢ΔͱͷґଘΛڧ੍Ͱ͖ΔͷͰΑΓ·͍͠ -
ࡐ֓ཁ • ϑϩϯτͱAjaxͰΓऔΓ͢ΔAPIαʔϏε • ݱߦͰRailsͰ࡞ΒΕ͍ͯͯɺࠓճϦϓϨʔε • ༷ݱߦ౿ऻ • ϞσϧActiveRecord͔Β٫ •
Scala + Play! Framework • ߴෛՙ • ग़དྷΔݶΓ1ͷϦΫΤετʹ͓͞Ί͍ͨ • σʔλετΞͳͲ֎෦ϦιʔεͷΞΫηε͕ूத @@'MJQEFTL@@ -
՝ • ActiveRecordΛ͍ͬͯͨ͜ͱͰɺϞσϧͱσʔλΞΫηε͕ ີʹͳ͍ͬͯͨ ˠͲͪΒͷ߹ʹҾͬுΒΕΔ • ϑΝοτϞσϧࢄݟ͞Εͨ ˠ͕ଟ͍ͱվम͕ߴ͍ • νϦੵΕͰɺߴෛՙʹͳͬͨͱ͖ʹશମ͕εϩʔμϯ
ˠͲ͜ͰσʔλΞΫηε͍ͯ͠Δͷ͔͏ͷ͕େมͳͷͰख͕ ଧͪʹ͍͘ -
DDD + Clean ArchitectureͰ σʔλΞΫηεΛίϯτϩʔϧ༰қʹ • DDDʹै͏ͱRepositoryΛ͏ݸॴΞϓϦέʔγϣ ϯαʔϏεʢUseCaseʣ͔υϝΠϯαʔϏεʹݶఆ͞ Ε͍ͯ͘ •
ू(Aggregate)͕ϥΠϑαΠΫϧ·Ͱ୲͏ͱ ͕େ͖͘ͳΓ͗͢ΔʢIDDD p.254ʣ • ࣗવͱσʔλΞΫηεݸॴ͕͔Γ͘͢ ※υϝΠϯαʔϏεɿෳͷΤϯςΟςΟʹ·͕ͨΔৼΔ͍ͳͲɺΤϯςΟςΟ͕ ࣋ͭʹద͞ͳ͍ৼΔ͍Λఆٛͨ͠υϝΠϯΦϒδΣΫτ -
DDD + Clean ArchitectureͰ σʔλΞΫηεΛίϯτϩʔϧ༰қʹ • ࠓͷͱ͜ΖυϝΠϯαʔϏεͰRepositoryΛ͍͍ͨέʔεग़͍ͯ ͳ͍ͷͰɺUseCaseͰͷΈRepositoryΛ͑ΔΑ͏ʹͯ͠ࢼ͍ͯ͠Δ • ҙਤͤͣԿݺͼग़ͯ͠͠·͏Մೳੑ͕͋Δˍ͑Δঢ়ଶͩͱ
͍ͨ͘ͳΔͷ͕ਓͳͷͰActiveRecordͷೋͷ͍ʹͳΒͳ͍Α͏ ҙΛ͍ͬͯΔ • ґଘؔنଇʹΑ͕ͬͯด͡ΒΕ͍ͯΔͷͰɺͲ͜ͰσʔλΞΫ ηε͍ͯ͠Δ͔͔Γ͘͢ͳͬͨ • σʔλετΞ͕Ұ൪֎ͳͷͰަ͕͘͢͠ͳͬͨɻElasticsearch ൛ͱDynamo൛ͰύϑΥʔϚϯεൺֱ͔ͯ͠Β࠾༻ΛܾΊΔՄೳ -
ิɿRepository I/F • αϯϓϧͰԠ༻ൣғΊʹDomainʹஔ͍͍ͯ·͢ ͕ɺϓϩμΫτͰContractʹஔ͍͍ͯ·͢ • PortʹRepositoryͱଊ͑ͯUseCaseͰͷΈΞΫηεΛ ڐՄʢI/FΛஔ͖ʣ͠ɺͦͷPort(Repository)ͷ࣮ʢܧ ঝʣ͕AdapterͰ͞Ε͍ͯΔɺͱ͍͏ղऍ •
RepositoryΛͲ͏͢Δ͔"ઃܭͷ՝" υϝΠϯϞσϧΛߟ͑Δ͏͑Ͱຊ࣭Ͱͳ͍ -
τϥϯβΫγϣϯʹ͍ͭͯ • "ूʢAggregateʣτϥϯβΫγϣϯ߹ੑͷڥքͱಉٛ" ʢIDDD p.340ʣͳͷͰɺҰͭͷूΛѻ͍ͬͯΔؒRepositoryͷ தʹด͡Δ͜ͱ͕Ͱ͖Δɻ • ɺෳͷूͷߋ৽Λ୯ҰͷτϥϯβΫγϣϯͰߦΘͳ͚ Ε͍͚ͳ͍࣌ 1.
݁Ռ߹ੑͰेͰͳ͍͔Λݕ౼͢Δ ˠτϥϯβΫγϣϯͷແ͍ੈքʢႈͳૢ࡞ඞཁʣ 2. ৽͍͠ूͱͯ͠ఆٛ͢Δ ˠ͜ΕΛ܁Γฦ͢ͱڊେͳूʹͳͬͯ͠·͏ͷͰҙ -
͍͟DDDΛ࣮ફ͠Α͏ͱ͢Δͱ • Կ͔Β࢝Ίͯྑ͍͔͔Βͳ͍ • υϝΠϯΤΩεύʔτͱͲ͏ͤྑ͍͔͔Βͳ͍ • UIແ͠ͰυϝΠϯ͚ͩΛ্ͯ͠ख͘ΘΒͳ͍ • ࠷ॳ͔ΒৄࡉͳΫϥεਤΛॻ͜͏ͱͯ͠͠·͏ •
ࢼ͠ʹϞσϧ͚ͩͰॻ͍ͯΈΔͱࢥ͍ͷ֎ϘϦϡʔϛΟ • υϝΠϯϞσϧʢΫϥεਤʣ͔Β༷ΛಡΈऔΔͷ͕ࠔ • ૾ͯ͠ಡΈऔΖ͏ͱ͢Δͱᐆດ͞ʹ໘͢Δ ㅟ ㅟ ㅟ ※ฐࣾࣄྫ͚ͩͰͳ͘ໝؚ·Ε·͢ -
ॻ੶ ʮϢʔεέʔεۦಈ։ൃ࣮ફΨΠυʯ • Use Case Driven Object Modeling with UML
• ICONIXϓϩηεͷղઆຊ • ඇৗʹܰշͳޠΓޱʢ͏ͻΌʔͱ͔ग़ͯ͘Δʣ • एׯXP൱ఆʢߟ͑ࣗମXPΑΓલ͔Β͋Δʣ • ͍͖ͳΓઃܭʹೖΔͷͰͳͯ͘ɺ·ͣੳΛͪΌΜͱ͠Α͏ɻ • ಛʹʮՄೳͳݶΓ؆୯ʹ(DTSTTCPW)ʯͱʮͦΜͳͷඞཁͳ͍ (YAGNI)ʯΛཧ༝ʹସίʔεʢΤϥʔέʔεʣΛߟྀʹؚΊͳ͍ ͜ͱഁ໓ͷಓͱ͍ͯ͠Δɻ -
ཁٻϑΣʔζ 1. ސ٬͔Βେখ༷ʑͳػೳཁٻ͕ग़ͯ͘Δ ʢཁٻऩूICONIXͷൣғ֎ɺॻ੶ʹΞυόΠεܝࡌʣ 2. υϝΠϯϞσϧͰݴ༿Λ౷Ұ͢Δͱ͜Ζ͔Β࢝ΊΔ 3. ࢴࣳډʢϓϩτλΠϓʣΛͬͯސ٬͔ΒৼΔ͍ཁٻΛ ฉ͖ग़͢ 4.
υϥϑτ൛ͷϢʔεέʔεΛ࡞͢Δ 5. ސ٬ͱҰॹʹϨϏϡʔΛߦ͏ ㅟ ㅟ ㅟ -
ੳϑΣʔζ 1. υϥϑτ൛Ϣʔεέʔε͔ΒϩόετωεੳΛߦ͏ 2. ݟམͱͨ͠Ϋϥεͷൃݟᐆດ͞Λআڈͨ݁͠ՌΛυϝΠϯϞσϧʹ ϑΟʔυόοΫ͢Δ 3. ʢϩόετωεਤதͷʣίϯτϩʔϥʹ໌֬ͳ໊લΛ͚Δ ˠ͜Ε͕"ৼΔ·͍"ʹͳΔ 4.
υϥϑτ൛ϢʔεέʔεΛॻ͖͢ 5. ސ٬ͱҰॹʹϨϏϡʔΛߦ͏ ㅟ ㅟ ㅟ ※ੳʙ࣮ϑΣʔζϢʔεέʔε୯ҐʹΠςϨʔςΟϒʹߦ͏ -
࣮ϑΣʔζ 1. ίʔσΟϯάɾ୯ମςετ 2. Ϣʔεέʔεʹج͍ͮͨ݁߹ςετΛߦ͏ 3. ʢγεςϜςετσϓϩΠʣ 4. ࣍ͷΠςϨʔγϣϯʹ͚ͯɺίʔυϨϏϡʔ ͱυϝΠϯϞσϧͷߋ৽Λߦ͏
5. ੳϑΣʔζʹΓɺ࣍ͷϢʔεέʔεΛਐΊΔ -
ੳͷඞཁੑ • DDDͰ७ਮͳੳϞσϧΛ൱ఆ͍ͯ͠Δ • ७ਮͳੳϞσϧίʔσΟϯά͕࢝·ΔͱࣺͯΒΕͯ͠·͏ ͜ͱ͕ཧ༝ɻ͕ɺ͜Ε։ൃऀͱੳऀ͕͔Ε͍ͯΔલఏ • ʮੳͱઃܭͷؒʹக໋తͳُ྾͕ੜ͡ΔͨΊɺͦΕͧΕͷ ࡞ۀͰಘΒΕΔಎޓ͍ʹ׆͔͞ΕΔ͜ͱ͕ͳ͍ͷͩɻʯ •
ʮࣝΛטΈࡅ͘ऀϞσϧͱઃܭ͓ΑͼίʔυΛ୯Ұͷ׆ಈ ͱͯ͠վྑ͠ଓ͚ΔΠςϨʔςΟϒͳϓϩηεͱͳΔʯ (DDD p.46 - 47) -
XPͱͷؔ • XP͋͘·ͰʮՁɾݪଇɾϓϥΫςΟεʯɻICONIXੳ͓ ΑͼઃܭͷϞσϦϯάϓϩηεͳͷͰɺछʑͷํ๏ʹద༻͢͠ ͍ɻ • ʮຊͷސ٬ࢀՃʯ͕͍͜͠ͱΛड़͍ͯΔɻͦͷͨΊʹɺϨ ϏϡʔΛϓϩηεʹΈࠐΜͰ͍Δɻ ˠνʔϜʹΑͬͯςʔϥϦϯά͢Εྑ͍ •
ICONIXϓϩηεͰɺετʔϦʔ͔Β͙͢ίʔυΛॻ͖࢝Ίͳ͍ ˠνʔϜͷशख़نʹΑͬͯςʔϥϦϯά͢Εྑ͍ ɹ͔͠͠ɺυϝΠϯࣝΛ๛ʹͭϓϩάϥϚͷํ͕গͳ͍ݱ࣮ -
Clean Architectureͱͷੑ • "UseCase"ͱͦͷ·Μ·ͷ͕͋ΔͷͰ͕͔ؔΓ͍͢ʢ"ΞϓϦέʔ γϣϯαʔϏε"ͱ͍͏ݴ༿ΑΓྑ͍ͱࢥ͏ɻϢʔεέʔεͱ͍͏ݴ༿Ͱͳ͍ ͷɺʢICONIXͳͲΛΘͳ͍ͱʣৄࡉͳٕज़ཁૉΛೖΕͯ͠·͍͍͔͢Β Ͱʁʣ • ۩ମతͳϑϨʔϜϫʔΫDB͕ܾ·͍ͬͯͳͯ͘։ൃΛਐΊΔ͜ͱ͕Ͱ͖Δ •
ICONIXϓϩηεUseCaseͱDomainͷؔ৺ࣄʹ͍ͭͯѻ͏ • Clean ArchitectureΞϓϦέʔγϣϯʢUseCase&DomainʣͱΠϯϑϥΛ ͢Δ • HexagonalOnionͰಉ༷ -
ద༻ͷߟ̍ ਖ਼ࣜͳυΩϡϝϯτʹ͠ͳ͍ • ސ٬ͱʮԿΛͭ͘Δͷ͔ʯΛᐆດ͞Λղফͯ͠߹ҙ͢Δ͜ͱ͕େࣄ • ICONIXϓϩηεͰʮ࡞͢ΔυΩϡϝϯτ͜ΕͰɺͦΕΛϨ Ϗϡʔ͢Δػձ͍ͭʯΛ໌֬ʹఆ͍ٛͯ͠Δɻ • ਖ਼֬ʹॻ͘͜ͱਪ͍ͯ͠ͳ͍ʢॏްͳυΩϡϝϯτ ᐫʣɻUML༷ʹ४ڌ͢Δඞཁͳ͍ɻۃͳɺϗϫΠτ
Ϙʔυͷམॻ͖Ͱྑ͍ʢͱࢥ͏ʣɻ • ॻ੶தͰπʔϧΛ͏͜ͱΛલఏʹɺίʔυͱઃܭΛಉظ͢ Δ͜ͱڧ͘ਪ͞Ε͍ͯΔɻࢴͱԖච͕Ұ൪ڧ͍͔͠Εͳ ͍ɻʮΊͰ͘͢ʯͱ͔ࢼͯ͠Έ͍ͨɻ -
ద༻ͷߟ̎ ߹ੑཁٻͷݕ౼ • ސ٬͕ࢀՃ͢ΔϨϏϡʔ༧උઃܭϨϏϡʔ·ͰʢγʔέϯεਤҎ ٕ߱ज़త͗͢ΔʣɻؾΛ͚ͭͳ͍ͱϩόετωεੳͷஈ֊Ͱ ߹ੑཁٻͷදݱ·Ͱٴͳ͍ؾ͕͢Δɻ • શͯʹτϥϯβΫγϣϯ͕ඞཁͱݶΒͣɺ݁Ռ߹ੑͰे ͳέʔεଟ͍ͣɻ •
༧උઃܭϨϏϡʔͷஈ֊·Ͱʹ߹ੑͷཁٻʢϨϕϧʣʹ͍ͭ ͯݕ౼ͨ͠ํ͕ྑ͍ͱࢥ͏ɻ • "τϥϯβΫγϣϯͷੳΛ͔ͯ͠ΒͰͳ͍ͱɺूͷઃܭͷྑ ͠ѱ͠Λਖ਼͘͠அ͢Δ͜ͱͰ͖ͳ͍"ʢIDDD p.340-344ʣ -
·ͱΊ • DDD + Clean Architecture + Use Case Driven
Object Modeling(ICONIX) ͷηοτ૬ੑ͕ྑͦ͞͏ • ICONIXܰྔͱ͍͑ɺͦͷதͰͲ͜·ͰΛ࣮ࢪ͢Δ͔ ސ٬νʔϜͱςʔϥϦϯάͨ͠ํ͕ྑ͍͔ • ֖Λ։͚Ε͍ͬͯΔਓʹͨΓલ… ૣ͘Γ͔ͨͬͨ ʢଞͷ࣮ફख๏͝ଘͷํ͕͍Βͬ͠ΌΕޙͰڭ͍͑ͯͩ͘͞ʣ -
Q & A vol.1 • Q.Contractͷ༝དྷʁ A.֎ଆͷͰ͏ͨΊʹɺ͜ͷϢʔεέʔε͜ͷ͕͋Γ·͢ͱܖ͍ͯ͠ ·͢ɻ͜ͷΠϯλϑΣʔεΛஔ͘Ͱ͢ɻαϯϓϧͰলུ͍ͯ͠·͕ͨ͠DTO ͷΑ͏ͳϢʔεέʔε͕ඞཁͱ͢ΔͷؚΈ·͢ɻ •
Q.CQRSͱͷੑʁ A.͝ΊΜͳ͍͞ɺ·ͩ໌֬ͳ͕͑Ͱ͖ͳ͍Ͱ͢ɻΞʔΩςΫνϟߏΛͭ͘ ΔͨΊͷͷͳͷͰɺద༻Ͱ͖ͳ͍͜ͱͳ͍ͱࢥ͍ͬͯ·͢ɻ͕ɺޙͷεϥ ΠυͷΑ͏ʹϩοΫΠϯ͞Εͨํָ͕ͳ͜ͱ͋Γ·͢ɻ ҰԿ͔͠ΒͷϑϨʔϜϫʔΫΛ͑ɺجຊ͍ଓ͚ΔΑͶͱ͍͏ߟ͑ݱ࣮ ղͱͯ͠ΞϦͳͷͰɺνʔϜɺͻ͍ͯϓϩμΫτͱͯ͠Ͳ͏͍͏ઓུΛͱΔ ͔ɺͰ͢ɻݸਓతʹϩοΫΠϯ͞ΕͣʹυϝΠϯͷಠཱੑΛอͭಓΛࡧͨ͠ ͍Ͱ͢Ͷɻ -
Q & A vol.2 • Q.Clean ArchitectureΛಋೖ͢ΔͨΊͷΞυόΠεʁ A.͋͘·ͰΞʔΩςΫνϟͳͷͰMVCΛ࠾༻͠·͔͢ʁDCIΛ࠾༻͠·͢ ͔ʁͱಉ͡ઢͷԆͰ͢ɻνʔϜͰཧղ͍͢͠ͷΛ·ͣ͠߹͏ͷͲ ͏Ͱ͠ΐ͏͔ʁ్தͰม͑Δͷ͍͠ͱࢥ͍·͢ɻ
·ͣࠓճͷαϯϓϧΛԼʹͯ͠ɺҰ͔ͭೋͭϢʔεέʔεΛ࣮ͯ͠Έͯ ײ֮Λ௫Ήͷྑ͍͔͠Ε·ͤΜɻͨͩ͠ɺCallbackΛ͏ͷ͔Promise Λ͏ͷ͔ͷΑ͏ͳςʔϥϦϯάͨ͠ํ͕ྑ͍Ͱ͢ɻϓϥοτϑΥʔϜ ࠾༻ٕज़ͷ߹ͳͲɻ ະorܦݧ͕ͳ͚Εɺখ͞ͳͱ͜Ζ͔Β࢝Ί·͠ΐ͏ɻ࠷খͷܗ͕αϯϓ ϧίʔυͰ͢ɻඞཁʹԠͯ͡ɺ༧Ί༧ظͰ͖Δ͜ͱΛࡌ͍͖ͤͯ·͠ΐ͏ɻ ϕʔεΛ࡞Δ࣌ͷίπϩδοΫΛΉਓʹ͜͏ॻ͍ͯཉ͍͠ɺΛ૾ͯ͠ ੍͋͑ͯΛ࡞Δ͜ͱͱࢥ͍·͢ɻ -
ࢀߟɿDDDฤ • ॻ੶ʮΤϦοΫɾΤϰΝϯεͷυϝΠϯۦಈઃܭʯʢᠳӭࣾʣ • ॻ੶ʮ࣮ફυϝΠϯۦಈઃܭʯʢᠳӭࣾʣ • ਿຊ ܒ ࢯʮυϝΠϯۦಈઃܭ at
DDD.rb #5ʯ • ਿຊ ܒ ࢯʮ2ͭͷυϝΠϯϞσϧʕDDDͷؚҙʯ • ૿ా ږ ࢯʮ3ि࿈ଓDDDͦͷ1 υϝΠϯۦಈઃܭͷجຊΛཧղ͢Δʯ • ૿ా ږ ࢯʮ3ि࿈ଓDDDͦͷ2 ਂ͍Ϟσϧͷ୳ٻ(υϝΠϯۦಈઃܭ ୈ̏෦) ʯ • ૿ా ږ ࢯʮ3ि࿈ଓDDDͦͷ3 υϝΠϯۦಈઃܭ ઓུతઃܭ ʯ • InfoQʮυϝΠϯۦಈઃܭɾ։ൃͷ࣮ફʯ • InfoQʮίϯςΩετϚοϐϯάʹΑΔઓུతυϝΠϯۦಈઃܭʯ • InfoQʮShane HastieࢯɺϏδωε՝ʹର͢ΔΞδϟΠϧϚΠϯυηοτͷద༻ʹ͍ͭͯޠΔʯ -
ࢀߟɿClean Architectureฤ • ετϥςδοΫνϣΠεʮϨΠϠʔυΞʔΩςΫνϟʯ • Alistair Cockburn ࢯʮHexagonal Architectureʯʢ༁ɿ౻ ࢯʣ
• Jeffrey Palermo ࢯʮThe Onion Architectureʯ • Robert Martin ࢯʮThe Clean Architectureʯʢ༁ɿ౻ ࢯʣ • Thomas PIERRAIN ࢯʮA zoom on the hexagonal/clean/onion architectureʯ • InfoQʮυϝΠϯۦಈઃܭͱΦχΦϯΞʔΩςΫνϟʯ • InfoQʮΞʔΩςΫνϟͷతҙਤͰ͋ΓɺϑϨʔϜϫʔΫͰͳ͍ʯ • James Coglan ࢯʮ໋ྩܕͷίʔϧόοΫɺؔܕͷϓϩϛε: Node ͕ҳͨ͠࠷େͷػձʯ(༁ɿԬຊ ࢯ) • Togetter·ͱΊʮ”໋ྩܕͷίʔϧόοΫɺؔܕͷϓϩϛε”ͷԠʢͱͦͷޙʣʯ • _kondeiࢯʮ࣋ଓՄೳͳ։ൃΛࢦ͢ ~ υϝΠϯɾϢʔεέʔεۦಈʢΫϦʔϯΞʔΩςΫνϟʣ + ୯ํʹ੍ݶͨ͠ॲཧ + FRPʯ • ૿ా ږ ࢯʮυϝΠϯϞσϧத৺ͷΞʔΩςΫνϟʯ • Android cleanarchitecture -
ࢀߟɿϢʔεέʔεۦಈ։ൃฤ • ॻ੶ʮϢʔεέʔεۦಈ։ൃ࣮ફΨΠυʯʢᠳӭࣾʣ • ॻ੶ʮΤΫετϦʔϜϓϩάϥϛϯάୈ2൛৽༁ʯʢΦʔϜࣾʣ • ॻ੶ʮϢʔβʔετʔϦʔϚοϐϯάʯʢΦϥΠϦʔδϟύϯʣ • ૿ా ږ
ࢯʮ࣮ફ ICONIXϓϩηεɿγʔέϯεਤͱΫϥεਤʯ • ૿ా ږ ࢯʮ࣮ફ ICONIXϓϩηεɿυϝΠϯۦಈʯ • WikipediaʮICONIXϓϩηεʯ • EZʮϏδωεཁٻͷٸܹͳมԽʹରԠ͢Δ։ൃϓϩηεͱʁʯ