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
20k
ネイティブアプリでもFluxしたい
yonekawa
0
2.3k
freeeモバイルチームの変遷と進化
yonekawa
0
7.8k
ReactiveCocoa Pitfalls at freee
yonekawa
2
850
RAC用クラス拡張の作り方
yonekawa
2
2.9k
Dive into Joybox
yonekawa
5
1.7k
Other Decks in Programming
See All in Programming
CloudflareのChat Agent Starter Kitで簡単!AIチャットボット構築
syumai
2
510
時間軸から考えるTerraformを使う理由と留意点
fufuhu
16
4.8k
詳解!defer panic recover のしくみ / Understanding defer, panic, and recover
convto
0
250
意外と簡単!?フロントエンドでパスキー認証を実現する WebAuthn
teamlab
PRO
2
780
ぬるぬる動かせ! Riveでアニメーション実装🐾
kno3a87
1
230
HTMLの品質ってなんだっけ? “HTMLクライテリア”の設計と実践
unachang113
4
2.9k
Flutter with Dart MCP: All You Need - 박제창 2025 I/O Extended Busan
itsmedreamwalker
0
150
rage against annotate_predecessor
junk0612
0
170
Processing Gem ベースの、2D レトロゲームエンジンの開発
tokujiros
2
130
print("Hello, World")
eddie
2
530
個人軟體時代
ethanhuang13
0
330
複雑なフォームに立ち向かう Next.js の技術選定
macchiitaka
2
240
Featured
See All Featured
Git: the NoSQL Database
bkeepers
PRO
431
66k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
Designing for Performance
lara
610
69k
RailsConf 2023
tenderlove
30
1.2k
The Power of CSS Pseudo Elements
geoffreycrofte
77
6k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Statistics for Hackers
jakevdp
799
220k
Code Reviewing Like a Champion
maltzj
525
40k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
930
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.1k
Speed Design
sergeychernyshev
32
1.1k
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/