Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
iOSアプリの設計とDependency Injection
Search
Kenichi Yonekawa
November 20, 2016
Programming
22
17k
iOSアプリの設計とDependency Injection
iOSオールスターズ2
https://eventdots.jp/event/602872
Kenichi Yonekawa
November 20, 2016
Tweet
Share
More Decks by Kenichi Yonekawa
See All by Kenichi Yonekawa
Fluxで複雑な状態の変化を予測可能にするiOSアプリ開発
yonekawa
9
19k
ネイティブアプリでもFluxしたい
yonekawa
0
2.2k
freeeモバイルチームの変遷と進化
yonekawa
0
7.5k
ReactiveCocoa Pitfalls at freee
yonekawa
2
830
RAC用クラス拡張の作り方
yonekawa
2
2.9k
Dive into Joybox
yonekawa
5
1.7k
Other Decks in Programming
See All in Programming
Fixstars高速化コンテスト2024準優勝解法
eijirou
0
190
『改訂新版 良いコード/悪いコードで学ぶ設計入門』活用方法−爆速でスキルアップする!効果的な学習アプローチ / effective-learning-of-good-code
minodriven
28
4.1k
QA環境で誰でも自由自在に現在時刻を操って検証できるようにした話
kalibora
1
140
サーバーゆる勉強会 DBMS の仕組み編
kj455
1
300
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
1.4k
歴史と現在から考えるスケーラブルなソフトウェア開発のプラクティス
i10416
0
300
KMP와 kotlinx.rpc로 서버와 클라이언트 동기화
kwakeuijin
0
300
Flatt Security XSS Challenge 解答・解説
flatt_security
0
730
20年もののレガシープロダクトに 0からPHPStanを入れるまで / phpcon2024
hirobe1999
0
1k
traP の部内 ISUCON とそれを支えるポータル / PISCON Portal
ikura_hamu
0
180
為你自己學 Python
eddie
0
520
Fibonacci Function Gallery - Part 2
philipschwarz
PRO
0
210
Featured
See All Featured
Speed Design
sergeychernyshev
25
730
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
How to train your dragon (web standard)
notwaldorf
89
5.8k
Building a Scalable Design System with Sketch
lauravandoore
460
33k
RailsConf 2023
tenderlove
29
970
Raft: Consensus for Rubyists
vanstee
137
6.7k
GraphQLとの向き合い方2022年版
quramy
44
13k
Writing Fast Ruby
sferik
628
61k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
127
18k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.4k
Designing Experiences People Love
moore
139
23k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Transcript
@yonekawa J04ΞϓϦͷઃܭͱ %FQFOEFODZ*OKFDUJPO
None
None
None
None
%FQFOEFODZ*OKFDUJPO
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
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
Problem • TwitterApi͕௨৴ͷΓํʹґଘ͍ͯ͠Δɻ௨৴ͷΓํΛ ม͔͑ͨͬͨΒTwitterApiಉ࣌ʹม͑ͳ͍ͱ͍͚ͳ͍ɻ • ʮπΠʔτΛߘ͢ΔʯλεΫʹؔͷͳ͍ॳظԽॲཧ͕ଟ ͘ͳΓϝιουͷؔ৺ࣄ͕૿͑Δ • ௨৴ͷίʔυ͕ີ݁߹͍ͯ͠ΔͨΊpostTweetͷςετ͕ॻ ͖ͮΒ͍
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
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
Dependency Injection Pattern • ίϯϙʔωϯτͷؒͷґଘؔΛιʔείʔυ͔Βഉআ͠ɺ ֎෦͔ΒೖͰ͖ΔΑ͏ʹ͢ΔσβΠϯύλʔϯ • ίϯϙʔωϯτ͔ΒΠϯελϯεͷੜͦͷ۩ମతͳ࣮ ͱ͍ͬͨຊདྷඞཁͳ͍ؔ৺ࣄ͕औΓআ͔Ε࣮͕ͯγϯϓϧ ʹͳΔ
• ֎෦͔Βίϯϙʔωϯτͷ࣮Λ੍ޚͰ͖ΔͷͰɺ௨৴෦ ͚ͩϞοΫͨ͠ΓϢχοτςετ͕Γ͘͢ͳΔ
Problem • Tweeter͕૿͑ͨΒຖճTwitterApiͱHTTP ClientΛॳظԽ͠ ͔ͯͯ͠Βݺͼग़͞ͳ͍ͱ͍͚ͳ͍ • ࠶ར༻͢ΔͨΊʹίϯϙʔωϯτԽͯ͠ΔͷʹͦΕΛ͏ͨ Ίͷ४උ͕ଟ͘ͳͬͯ໘͍͘͞
DI Container • ґଘίϯϙʔωϯτͷੜͱೖΛผͷίϯϙʔωϯτʹ ͤΔɻDIίϯςφͱ͔DIϑϨʔϜϫʔΫͱݺΕΔͷ • ίϯςφίϯϙʔωϯτͷੜํ๏ͱೖํ๏Λ͍ͬͯ ͯɺίϯϙʔωϯτؒͷґଘؔΛղܾͯ͠ΦϒδΣΫτΛ ฦͯ͘͠ΕΔ DI
Container Client Code Tweeter TwitterApi HTTP Client
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
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
Clean Architecture • ϩδοΫͷͱׂΛׂ͢Δ͜ͱͰͦΕͧΕͷΛ໌ ֬ʹͯ͠ઃܭͷڞ௨ೝࣝΛ࡞ΔΞʔΩςΫνϟઃܭ • ׂΛׂͤ͞ΔʹͦΕͧΕͷίϯϙʔωϯτͷґଘؔ ΛΓ͢ඞཁ͕͋Δ • Clean
ArchitectureDIΛੵۃతʹ׆༻ͨ͠ʢ׆༻Ͱ͖Δʣ ΞʔΩςΫνϟ
%*'SBNFXPSLGPSJ04
Typical DI Frameworks • Typhoon • Swinject • Cleanse
Typhoon • Objective-C͔࣌Β͋ΔฮͷDIίϯςφ • Storyboard͔ΒͷΠϯελϯεੜαϙʔτɺplistͰͷґ ଘؔͷఆٛͳͲػೳ๛ • ࣮͕Objective-Cϕʔεͷ͍͔ͤSwiftͩͱܕͷѻ͍͕͋· Γ͏·͘ͳ͍
Swinject • Pure SwiftͰॻ͔ΕͨDIϑϨʔϜϫʔΫ • ContainerΦϒδΣΫτʹܕͱBlockΛొͯ͠ܕΛىʹґ ଘΛղܾ͢Δ • Typhoonͱҧ͍ɺຊମʹೖΕͨ͘ͳ͍͕ศརͳػೳ֦ு ͷܗͰఏڙ͍ͯ͠Δɻ
Swinject Style MFUDPOUBJOFS$POUBJOFS DPOUBJOFSSFHJTUFS "OJNBM5ZQFTFMG \@JO$BU OBNF.JNJ ^ DPOUBJOFSSFHJTUFS
1FSTPO5ZQFTFMG \SJO 1FU0XOFS QFUSSFTPMWF "OJNBM5ZQFTFMG ^ MFUQFSTPODPOUBJOFSSFTPMWF 1FSTPO5ZQFTFMG QFSTPOQMBZ
Cleanse • SquareͷDIίϯςφ • SwinjectͷContainerʹ૬͢Δͷແ͘ɺComponentͱ ModuleͷΈ߹ΘͤͰ֤ΦϒδΣΫτͷґଘΛཧ͢Δ • JavaͷDIϑϨʔϜϫʔΫ(Dagger)ʹΠϯεύΠΞ͞Ε͍ͯ ΔͷͰ༻ޠࣅ͍ͯΔ͕ɺSwiftͷݴޠ༷ʹ߹Θͤͯઃܭ ͞Ε͍ͯΔ
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
Swinject vs Cleanse • CleanseίϯϙʔωϯτఆٛͰΔ͜ͱ͕ଟ͍ͷͰ࠷ॳ ໘ɻSwinjectContainerʹܕͱBlockΛ͚ͩ͢Ͱ͍͍ͷ ͰΧδϡΞϧʹ͑Δɻ • ίϯϙʔωϯτͷੜํ๏Λίϯϙʔωϯτ୯ҐͰఆٛ͢ ΔCleanseͷ΄͏͕ΠϯλϑΣʔεͱͯ͠ے͕Αͦ͞͏ɻ
SwinjectContainerͷཧͱ͍͏ผͷ͕͋Δɻ • Cleanse·ͩbetaͰ͋·ΓίϛϡχςΟͷಈ͖͕ͳ͍
J04%*1SBDUJDF
Protocol Oriented • ίϯϙʔωϯτؒΛૄ݁߹ʹ͢ΔʹίϯϙʔωϯτͷΠ ϯλϑΣʔεΛ໌ࣔతʹ͠ͳ͍ͱ͍͚ͳ͍ɻΠϯλϑΣʔε ͕ಉ͡ͳΒ࣮ͷࠩ͠ସ͕͑༰қʹͳΔɻ QSPUPDPM)551$MJFOU\ GVODTFOE ^
DMBTT/463-4FTTJPO$MJFOU)551$MJFOU\ GVODTFOE \ /463-4FTTJPO EBUB5BTL8JUI3FRVFTU ǘ ^ ^ DMBTT"MBNPGJSF$MJFOU)551$MJFOU\ GVODTFOE \ "MBNPGJSFSFRVFTU ǘ ^ ^
Constructor Injection vs Property Injection • Property Injection֎෦ʹϓϩύςΟΛެ։͢Δඞཁ͕͋ ΓMutableʹ͠ͳ͍ͱ͍͚ͳ͍ͷͰجຊతʹConstructor InjectionΛ͓קΊ͍ͨ͠
• CleanseͷυΩϡϝϯτͰProperty Injection AppDelegateStoryboardͳͲΠϯελϯεੜΛ੍ޚͰ ͖ͳ͍έʔεͰ͏ͱ͞Ε͍ͯΔ
prepareForSegue • ભҠݩͷViewController͕ભҠઌͷViewControllerʹ͍ͭͯ Βͳ͍ͱ͍͚ͳ͍ɻભҠઌͷ༷͕มΘͬͨΒભҠݩΛ ͞ͳ͍ͱ͍͚ͳ͍ɻ • ΠϯελϯεԽStoryboardʹΑͬͯߦΘΕΔͷͰ PropertyInjectorΛͬͯೖ͢Δ PWFSSJEFGVODQSFQBSF'PS4FHVF TFHVF6*4UPSZCPBSE4FHVF
TFOEFS "OZ0CKFDU \ JGMFUWDTFHVFEFTUJOBUJPO7JFX$POUSPMMFSBT /FYU7JFX$POUSPMMFS\ MFUJOKFDUPSUSZ/FYU7JFX$POUSPMMFS$PNQPOFOU CVJME JOKFDUPSJOKFDU1SPQFSUJFT JOUPWD ^ ^
DI with arguments • ΠϯελϯεੜΛίϯςφʹͤͯ͠·͏ͷͰɺϢʔβʔ ೖྗͳͲͷಈతͳύϥϝʔλͲ͏͖͔͢ • CleanseComponentFactoryͱ͍͏ػೳͰͦΕΛ࣮ݱͰ͖ Δ͕·ͩ։ൃதɻݱঢ়ͰComponentͷॳظԽ࣌ʹύϥ ϝʔλΛͯ͠Moduleͷੜʹ͏͔͠ͳͦ͞͏
• SwinjectґଘΦϒδΣΫτΛresolve͢Δ࣌ʹੜίʔυ ͷύϥϝʔλ͕ͤΔ
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 ^ ^
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 ^ ^
Mock Testing • API௨৴෦ͳͲΛϢχοτςετͷ࣌ʹϞοΫ࣮ʹࠩ ͠ସ͍͑ͨɻ • CleanseModuleΛ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 ^
Do Not Use Fake Mode • ίϯϙʔωϯτఆٛΛ্ॻ͖͢Δͷίϯϙʔωϯτؒͷґଘͷ ࿈ΛಡΈͮΒ͘͢ΔͷͰΑ͘ͳ͍ʢCleanseͰ͜ͷػೳΛ আ͢ΔPR͕ग़ͯΔʣ •
ૉʹϢχοτςετ࣌ʹϞοΫ͢Δ͖ɻґଘΦϒδΣΫτ ԿΒ͔ͷܗͰ֎෦͔ΒͤΔઃܭʹͳ͍ͬͯΔ͔Β؆୯ͳͣ DMBTT5XJUUFS"QJ5FTUT9$5FTU$BTF\ WBSTVCKFDU5XJUUFS"QJ MFUTFTTJPO.PDL63-4FTTJPO PWFSSJEFGVODTFU6Q \ TVQFSTFU6Q TVCKFDU5XJUUFS"QJ TFTTJPOTFTTJPO ^ ^
Swiftʹ͓͚Δݱ࣮తͳϞοΫ https://realm.io/jp/news/tryswift-veronica-ray-real-world-mocking-swift/
·ͱΊ
·ͱΊ • ෳࡶͳΞϓϦͰมߋʹڧ͍ΞʔΩςΫνϟΛ࡞ΔͨΊʹ· ͣɺίϯϙʔωϯτؒͷґଘΛഉআ͢Δ͜ͱ͕ॏཁɻDIʹ ΑͬͯͦͷΛ࡞Δ͜ͱ͕Ͱ͖Δ • SwiftͷProtocolܕγεςϜΛ͏·ͬͨ͘DIϑϨʔϜϫʔ ΫΛ࠾༻͢ΔͱΞϓϦέʔγϣϯ͕ΑΓݎ࿚ʹͳΔ • ͍·ϓϩμΫγϣϯʹೖΕΔͳΒSwinject͕Αͦ͞͏͕ͩɺ
CleanseΠϯλϑΣʔε͕Α͘Ͱ͖͍ͯΔͷͰظ͍ͨ͠
Improving Existing Apps with Modern Best Practices https://developer.apple.com/videos/play/wwdc2016/213/