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

iOSアプリの設計とDependency Injection

iOSアプリの設計とDependency Injection

iOSオールスターズ2
https://eventdots.jp/event/602872

3fe447a7f9238108e6c50e97ac12717a?s=128

Kenichi Yonekawa

November 20, 2016
Tweet

Transcript

  1. @yonekawa J04ΞϓϦͷઃܭͱ %FQFOEFODZ*OKFDUJPO

  2. None
  3. None
  4. None
  5. None
  6. %FQFOEFODZ*OKFDUJPO

  7. Dependency? TUSVDU5XFFUFS\ GVODUXFFU UXFFU4USJOH \ MFUBQJ5XJUUFS"QJ  BQJQPTU5XFFU UXFFU 

    ^ ^ TUSVDU5XJUUFS"QJ\ GVODQPTU5XFFU UXFFU4USJOH \ MFUDPOGJH/463-4FTTJPO$POGJHVSBUJPOEFGBVMU4FTTJPO$POGJHVSBUJPO  MFUTFTTJPO/463-4FTTJPO DPOGJHVSBUJPODPOGJH  MFUSFRVFTUCVJMESFRVFTU TFTTJPOEBUB5BTL8JUI3FRVFTU SFRVFTU  ^ ^ MFUUXFFUFS5XFFUFS  UXFFUFSUXFFU )FMMP  Tweeter TwitterApi HTTP Client
  8. Dependency? TUSVDU5XFFUFS\ GVODUXFFU UXFFU4USJOH \ MFUBQJ5XJUUFS"QJ  BQJQPTU5XFFU UXFFU 

    ^ ^ TUSVDU5XJUUFS"QJ\ GVODQPTU5XFFU UXFFU4USJOH \ MFUDPOGJH/463-4FTTJPO$POGJHVSBUJPOEFGBVMU4FTTJPO$POGJHVSBUJPO  MFUTFTTJPO/463-4FTTJPO DPOGJHVSBUJPODPOGJH  MFUSFRVFTUCVJMESFRVFTU TFTTJPOEBUB5BTL8JUI3FRVFTU SFRVFTU  ^ ^ MFUUXFFUFS5XFFUFS  UXFFUFSUXFFU )FMMP  Tweeter TwitterApi HTTP Client
  9. Problem • TwitterApi͕௨৴ͷ΍Γํʹґଘ͍ͯ͠Δɻ௨৴ͷ΍ΓํΛ ม͔͑ͨͬͨΒTwitterApi΋ಉ࣌ʹม͑ͳ͍ͱ͍͚ͳ͍ɻ • ʮπΠʔτΛ౤ߘ͢ΔʯλεΫʹؔ܎ͷͳ͍ॳظԽॲཧ͕ଟ ͘ͳΓϝιουͷؔ৺ࣄ͕૿͑Δ • ௨৴ͷίʔυ͕ີ݁߹͍ͯ͠ΔͨΊpostTweetͷςετ͕ॻ ͖ͮΒ͍

  10. Solution TUSVDU5XFFUFS\ MFUBQJ5XJUUFS"QJ GVODUXFFU UXFFU4USJOH \ BQJQPTU5XFFU UXFFU  ^

    ^ TUSVDU5XJUUFS"QJ\ MFUIUUQ$MJFOU)551$MJFOU GVODQPTU5XFFU UXFFU4USJOH \ MFUSFRVFTUCVJMESFRVFTU IUUQ$MJFOUTFOE SFRVFTU  ^ ^ MFUBQJ5XJUUFS"QJ IUUQ$MJFOU)UUQ$MJFOU8JUI63-4FTTJPO  MFUUXFFUFS5XFFUFS BQJBQJ  UXFFUFSUXFFU )FMMP
  11. Solution TUSVDU5XFFUFS\ MFUBQJ5XJUUFS"QJ GVODUXFFU UXFFU4USJOH \ BQJQPTU5XFFU UXFFU  ^

    ^ TUSVDU5XJUUFS"QJ\ MFUIUUQ$MJFOU)551$MJFOU GVODQPTU5XFFU UXFFU4USJOH \ MFUSFRVFTUCVJMESFRVFTU IUUQ$MJFOUTFOE SFRVFTU  ^ ^ MFUBQJ5XJUUFS"QJ IUUQ$MJFOU)UUQ$MJFOU8JUI63-4FTTJPO  MFUUXFFUFS5XFFUFS BQJBQJ  UXFFUFSUXFFU )FMMP
  12. Dependency Injection Pattern • ίϯϙʔωϯτͷؒͷґଘؔ܎Λιʔείʔυ͔Βഉআ͠ɺ ֎෦͔Β஫ೖͰ͖ΔΑ͏ʹ͢ΔσβΠϯύλʔϯ • ίϯϙʔωϯτ͔ΒΠϯελϯεͷੜ੒΍ͦͷ۩ମతͳ࣮૷ ͱ͍ͬͨຊདྷඞཁͳ͍ؔ৺ࣄ͕औΓআ͔Ε࣮ͯ૷͕γϯϓϧ ʹͳΔ

    • ֎෦͔Βίϯϙʔωϯτͷ࣮૷Λ੍ޚͰ͖ΔͷͰɺ௨৴෦෼ ͚ͩϞοΫͨ͠ΓϢχοτςετ͕΍Γ΍͘͢ͳΔ
  13. Problem • Tweeter͕૿͑ͨΒຖճTwitterApiͱHTTP ClientΛॳظԽ͠ ͯ౉͔ͯ͠Βݺͼग़͞ͳ͍ͱ͍͚ͳ͍ • ࠶ར༻͢ΔͨΊʹίϯϙʔωϯτԽͯ͠ΔͷʹͦΕΛ࢖͏ͨ Ίͷ४උ͕ଟ͘ͳͬͯ໘౗͍͘͞

  14. DI Container • ґଘίϯϙʔωϯτͷੜ੒ͱ஫ೖΛผͷίϯϙʔωϯτʹ ೚ͤΔɻDIίϯςφͱ͔DIϑϨʔϜϫʔΫͱݺ͹ΕΔ΋ͷ • ίϯςφ͸ίϯϙʔωϯτͷੜ੒ํ๏ͱ஫ೖํ๏Λ஌͍ͬͯ ͯɺίϯϙʔωϯτؒͷґଘؔ܎Λղܾͯ͠ΦϒδΣΫτΛ ฦͯ͘͠ΕΔ DI

    Container Client Code Tweeter TwitterApi HTTP Client
  15. Pseudocode SFHJTUFS )551$MJFOUTFMG \ )551$MJFOUJO SFUVSO)UUQ$MJFOU8JUI63-4FTTJPO  ^ SFHJTUFS 5XJUUFS"QJTFMG

    \ 5XJUUFS"QJJO MFUVSM4FTTJPODPNQPOFOU /463-4FTTJPOTFMG  SFUVSO5XJUUFS"QJ VSM4FTTJPOVSM4FTTJPO  ^ SFHJTUFS 5XFFUFSTFMG \ 5XFFUFSJO MFUBQJDPNQPOFOU 5XJUUFS"QJTFMG  SFUVSO5XFFUFS BQJBQJ  ^ MFUUXFFUFSDPNQPOFOU 5XFFUFSTFMG  UXFFUFSUXFFU )FMMP 
  16. Pseudocode SFHJTUFS )551$MJFOUTFMG \ )551$MJFOUJO SFUVSO"MBNPGJSF$MJFOU  ^ SFHJTUFS 5XJUUFS"QJTFMG

    \ 5XJUUFS"QJJO MFUVSM4FTTJPODPNQPOFOU /463-4FTTJPOTFMG  SFUVSO5XJUUFS"QJ VSM4FTTJPOVSM4FTTJPO  ^ SFHJTUFS 5XFFUFSTFMG \ 5XFFUFSJO MFUBQJDPNQPOFOU 5XJUUFS"QJTFMG  SFUVSO5XFFUFS BQJBQJ  ^ MFUUXFFUFSDPNQPOFOU 5XFFUFSTFMG  UXFFUFSUXFFU )FMMP 
  17. Clean Architecture • ϩδοΫͷ૚ͱ໾ׂΛ෼ׂ͢Δ͜ͱͰͦΕͧΕͷ੹຿Λ໌ ֬ʹͯ͠ઃܭͷڞ௨ೝࣝΛ࡞ΔΞʔΩςΫνϟઃܭ • ໾ׂΛ෼ׂͤ͞Δʹ͸ͦΕͧΕͷίϯϙʔωϯτͷґଘؔ܎ Λ੾Γ཭͢ඞཁ͕͋Δ • Clean

    Architecture͸DIΛੵۃతʹ׆༻ͨ͠ʢ׆༻Ͱ͖Δʣ ΞʔΩςΫνϟ
  18. %*'SBNFXPSLGPSJ04

  19. Typical DI Frameworks • Typhoon • Swinject • Cleanse

  20. Typhoon • Objective-C࣌୅͔Β͋Δ࿝ฮͷDIίϯςφ • Storyboard͔ΒͷΠϯελϯεੜ੒αϙʔτ΍ɺplistͰͷґ ଘؔ܎ͷఆٛͳͲػೳ͸๛෋ • ࣮૷͕Objective-Cϕʔεͷ͍͔ͤSwiftͩͱܕͷѻ͍͕͋· Γ͏·͘ͳ͍

  21. Swinject • Pure SwiftͰॻ͔ΕͨDIϑϨʔϜϫʔΫ • ContainerΦϒδΣΫτʹܕͱBlockΛొ࿥ͯ͠ܕΛى఺ʹґ ଘΛղܾ͢Δ • Typhoonͱҧ͍ɺຊମʹೖΕͨ͘ͳ͍͕ศརͳػೳ͸֦ு ͷܗͰఏڙ͍ͯ͠Δɻ

  22. Swinject Style MFUDPOUBJOFS$POUBJOFS  DPOUBJOFSSFHJTUFS "OJNBM5ZQFTFMG \@JO$BU OBNF.JNJ ^ DPOUBJOFSSFHJTUFS

    1FSTPO5ZQFTFMG \SJO 1FU0XOFS QFUSSFTPMWF "OJNBM5ZQFTFMG   ^ MFUQFSTPODPOUBJOFSSFTPMWF 1FSTPO5ZQFTFMG  QFSTPOQMBZ 
  23. Cleanse • Square੡ͷDIίϯςφ • SwinjectͷContainerʹ૬౰͢Δ΋ͷ͸ແ͘ɺComponentͱ Moduleͷ૊Έ߹ΘͤͰ֤ΦϒδΣΫτͷґଘΛ؅ཧ͢Δ • JavaͷDIϑϨʔϜϫʔΫ(Dagger)ʹΠϯεύΠΞ͞Ε͍ͯ ΔͷͰ༻ޠ͸ࣅ͍ͯΔ͕ɺSwiftͷݴޠ࢓༷ʹ߹Θͤͯઃܭ ͞Ε͍ͯΔ

  24. Cleanse Style TUSVDU"OJNBM.PEVMF$MFBOTF.PEVMF\ GVODDPOGJHVSF##JOEFS CJOEFSCJOEFS# \ CJOEFSCJOE "OJNBM5ZQFTFMG UP WBMVF$BU

    OBNF.JNJ  ^ ^ TUSVDU0XOFS$PNQPOFOU$MFBOTF$PNQPOFOU\ UZQFBMJBT3PPU1FSTPO5ZQF GVODDPOGJHVSF##JOEFS CJOEFSCJOEFS# \ CJOEFSJOTUBMM NPEVMF"OJNBM.PEVMF  CJOEFSCJOE 1FSTPO5ZQFTFMG UP GBDUPSZ1FU0XOFSJOJU  ^ ^ MFUQFSTPOUSZ0XOFS$PNQPOFOU CVJME  QFSTPOQMBZ
  25. Swinject vs Cleanse • Cleanse͸ίϯϙʔωϯτఆٛͰ΍Δ͜ͱ͕ଟ͍ͷͰ࠷ॳ͸ ໘౗ɻSwinject͸ContainerʹܕͱBlockΛ౉͚ͩ͢Ͱ͍͍ͷ ͰΧδϡΞϧʹ࢖͑Δɻ • ίϯϙʔωϯτͷੜ੒ํ๏Λίϯϙʔωϯτ୯ҐͰఆٛ͢ ΔCleanseͷ΄͏͕ΠϯλϑΣʔεͱͯ͠͸ے͕Αͦ͞͏ɻ

    Swinject͸Containerͷ؅ཧͱ͍͏ผͷ໰୊͕͋Δɻ • Cleanse͸·ͩbetaͰ͋·ΓίϛϡχςΟͷಈ͖͕ͳ͍
  26. J04%*1SBDUJDF

  27. Protocol Oriented • ίϯϙʔωϯτؒΛૄ݁߹ʹ͢Δʹ͸ίϯϙʔωϯτͷΠ ϯλϑΣʔεΛ໌ࣔతʹ͠ͳ͍ͱ͍͚ͳ͍ɻΠϯλϑΣʔε ͕ಉ͡ͳΒ࣮૷ͷࠩ͠ସ͕͑༰қʹͳΔɻ QSPUPDPM)551$MJFOU\ GVODTFOE  ^

    DMBTT/463-4FTTJPO$MJFOU)551$MJFOU\ GVODTFOE \ /463-4FTTJPO EBUB5BTL8JUI3FRVFTU ǘ  ^ ^ DMBTT"MBNPGJSF$MJFOU)551$MJFOU\ GVODTFOE \ "MBNPGJSFSFRVFTU ǘ  ^ ^
  28. Constructor Injection vs Property Injection • Property Injection͸֎෦ʹϓϩύςΟΛެ։͢Δඞཁ͕͋ ΓMutableʹ͠ͳ͍ͱ͍͚ͳ͍ͷͰجຊతʹ͸Constructor InjectionΛ͓קΊ͍ͨ͠

    • CleanseͷυΩϡϝϯτͰ͸Property Injection͸ AppDelegate΍StoryboardͳͲΠϯελϯεੜ੒Λ੍ޚͰ ͖ͳ͍έʔεͰ࢖͏ͱ͞Ε͍ͯΔ
  29. prepareForSegue • ભҠݩͷViewController͕ભҠઌͷViewControllerʹ͍ͭͯ ஌Βͳ͍ͱ͍͚ͳ͍ɻભҠઌͷ࢓༷͕มΘͬͨΒભҠݩΛ ௚͞ͳ͍ͱ͍͚ͳ͍ɻ • ΠϯελϯεԽ͸StoryboardʹΑͬͯߦΘΕΔͷͰ PropertyInjectorΛ࢖ͬͯ஫ೖ͢Δ PWFSSJEFGVODQSFQBSF'PS4FHVF TFHVF6*4UPSZCPBSE4FHVF

    TFOEFS "OZ0CKFDU \ JGMFUWDTFHVFEFTUJOBUJPO7JFX$POUSPMMFSBT /FYU7JFX$POUSPMMFS\ MFUJOKFDUPSUSZ/FYU7JFX$POUSPMMFS$PNQPOFOU CVJME  JOKFDUPSJOKFDU1SPQFSUJFT JOUPWD  ^ ^
  30. DI with arguments • Πϯελϯεੜ੒Λίϯςφʹ೚ͤͯ͠·͏ͷͰɺϢʔβʔ ೖྗͳͲͷಈతͳύϥϝʔλ͸Ͳ͏౉͢΂͖͔ • Cleanse͸ComponentFactoryͱ͍͏ػೳͰͦΕΛ࣮ݱͰ͖ Δ͕·ͩ։ൃதɻݱঢ়Ͱ͸ComponentͷॳظԽ࣌ʹύϥ ϝʔλΛ౉ͯ͠Moduleͷੜ੒ʹ࢖͏͔͠ͳͦ͞͏

    • Swinject͸ґଘΦϒδΣΫτΛresolve͢Δ࣌ʹੜ੒ίʔυ ΁ͷύϥϝʔλ͕౉ͤΔ
  31. DI with arguments (Cleanse) TUSVDU/FYU7JFX$PNQPOFOU$MFBOTF$PNQPOFOU\ MFUJUFN*UFN UZQFBMJBT3PPU1SPQFSUZ*OKFDUPS/FYU7JFX$POUSPMMFS GVODDPOGJHVSF##JOEFS CJOEFSCJOEFS# \

    CJOEFSJOTUBMM NPEVMF7JFX.PEFM.PEVMF  CJOEFS CJOE1SPQFSUZ*OKFDUJPO0G /FYU7JFX$POUSPMMFSTFMG  UP\ WD/FYU7JFX$POUSPMMFS WJFX.PEFM7JFX.PEFM JO WJFX.PEFMJUFNJUFN WDWJFX.PEFMWJFX.PEFM ^ ^ ^ PWFSSJEFGVODQSFQBSF'PS4FHVF TFHVF6*4UPSZCPBSE4FHVF TFOEFS"OZ0CKFDU \ JGMFUWDTFHVFEFTUJOBUJPO7JFX$POUSPMMFSBT /FYU7JFX$POUSPMMFS\ MFUJUFN MFUJOKFDUPSUSZ/FYU7JFX$PNQPOFOU JUFNJUFN CVJME  JOKFDUPSJOKFDU1SPQFSUJFT JOUPWD  ^ ^
  32. DI with arguments (Cleanse) TUSVDU/FYU7JFX$PNQPOFOU$MFBOTF$PNQPOFOU\ MFUJUFN*UFN UZQFBMJBT3PPU1SPQFSUZ*OKFDUPS/FYU7JFX$POUSPMMFS GVODDPOGJHVSF##JOEFS CJOEFSCJOEFS# \

    CJOEFSJOTUBMM NPEVMF7JFX.PEFM.PEVMF  CJOEFS CJOE1SPQFSUZ*OKFDUJPO0G /FYU7JFX$POUSPMMFSTFMG  UP\ WD/FYU7JFX$POUSPMMFS WJFX.PEFM7JFX.PEFM JO WJFX.PEFMJUFNJUFN WDWJFX.PEFMWJFX.PEFM ^ ^ ^ PWFSSJEFGVODQSFQBSF'PS4FHVF TFHVF6*4UPSZCPBSE4FHVF TFOEFS"OZ0CKFDU \ JGMFUWDTFHVFEFTUJOBUJPO7JFX$POUSPMMFSBT /FYU7JFX$POUSPMMFS\ MFUJUFN MFUJOKFDUPSUSZ/FYU7JFX$PNQPOFOU JUFNJUFN CVJME  JOKFDUPSJOKFDU1SPQFSUJFT JOUPWD  ^ ^
  33. Mock Testing • API௨৴෦෼ͳͲΛϢχοτςετͷ࣌ʹ͸ϞοΫ࣮૷ʹࠩ ͠ସ͍͑ͨɻ • Cleanse͸ModuleΛOverride͢Δ͜ͱ͕Ͱ͖ΔͷͰϞοΫ ࣮૷ͱͷࠩ͠ସ͕͑༰қ͚ͩͲɾɾɾ TUSVDU'BLF.PEVMF0WFSSJEF.PEVMF\ UZQFBMJBT0WFSSJEFT5XFFUFS$PNQPOFOU

    GVODDPOGJHVSF##JOEFS CJOEFSCJOEFS# \ CJOEFSJOTUBMM NPEVMF'BLF5XJUUFS"QJ.PEVMF  ^ ^ JGVTF'BLF.PEF\ JOKFDUPSUSZ$PNQPOFOU XJUI0WFSSJEFT PWFSSJEF.PEVMF'BLF.PEVMF CVJME  ^FMTF\ JOKFDUPSUSZ$PNQPOFOU CVJME  ^
  34. Do Not Use Fake Mode • ίϯϙʔωϯτఆٛΛ্ॻ͖͢Δͷ͸ίϯϙʔωϯτؒͷґଘͷ ࿈࠯ΛಡΈͮΒ͘͢ΔͷͰΑ͘ͳ͍ʢCleanseͰ΋͜ͷػೳΛ࡟ আ͢ΔPR͕ग़ͯΔʣ •

    ૉ௚ʹϢχοτςετ࣌ʹϞοΫ͢Δ΂͖ɻґଘΦϒδΣΫτ͸ ԿΒ͔ͷܗͰ֎෦͔Β౉ͤΔઃܭʹͳ͍ͬͯΔ͔Β؆୯ͳ͸ͣ DMBTT5XJUUFS"QJ5FTUT9$5FTU$BTF\ WBSTVCKFDU5XJUUFS"QJ MFUTFTTJPO.PDL63-4FTTJPO  PWFSSJEFGVODTFU6Q \ TVQFSTFU6Q  TVCKFDU5XJUUFS"QJ TFTTJPOTFTTJPO  ^ ^
  35. Swiftʹ͓͚Δݱ࣮తͳϞοΫ https://realm.io/jp/news/tryswift-veronica-ray-real-world-mocking-swift/

  36. ·ͱΊ

  37. ·ͱΊ • ෳࡶͳΞϓϦͰมߋʹڧ͍ΞʔΩςΫνϟΛ࡞ΔͨΊʹ͸· ͣɺίϯϙʔωϯτؒͷґଘΛഉআ͢Δ͜ͱ͕ॏཁɻDIʹ Αͬͯͦͷ౔৕Λ࡞Δ͜ͱ͕Ͱ͖Δ • SwiftͷProtocol΍ܕγεςϜΛ͏·͘࢖ͬͨDIϑϨʔϜϫʔ ΫΛ࠾༻͢ΔͱΞϓϦέʔγϣϯ͕ΑΓݎ࿚ʹͳΔ • ͍·ϓϩμΫγϣϯʹೖΕΔͳΒSwinject͕Αͦ͞͏͕ͩɺ

    Cleanse͸ΠϯλϑΣʔε͕Α͘Ͱ͖͍ͯΔͷͰظ଴͍ͨ͠
  38. Improving Existing Apps with Modern Best Practices https://developer.apple.com/videos/play/wwdc2016/213/