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.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
Linux && Docker 研修/Linux && Docker training
forrep
24
4.5k
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
100
GitHub Actions × RAGでコードレビューの検証の結果
sho_000
0
260
お前もAI鬼にならないか?👹Bolt & Cursor & Supabase & Vercelで人間をやめるぞ、ジョジョー!👺
taishiyade
6
4k
昭和の職場からアジャイルの世界へ
kumagoro95
1
380
コミュニティ駆動 AWS CDK ライブラリ「Open Constructs Library」 / community-cdk-library
gotok365
2
120
第3回 Snowflake 中部ユーザ会- dbt × Snowflake ハンズオン
hoto17296
4
370
Immutable ActiveRecord
megane42
0
140
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
2
290
技術を根付かせる / How to make technology take root
kubode
1
250
Introduction to kotlinx.rpc
arawn
0
700
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
740
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1368
200k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
Fireside Chat
paigeccino
34
3.2k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Designing for humans not robots
tammielis
250
25k
Building Your Own Lightsaber
phodgson
104
6.2k
Code Reviewing Like a Champion
maltzj
521
39k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
40
2k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.6k
Why Our Code Smells
bkeepers
PRO
336
57k
Visualization
eitanlees
146
15k
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/