Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
我々のRealmはどこからやってくるのか
Search
Tomohiro Nishimura
March 26, 2017
Programming
450
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
我々のRealmはどこからやってくるのか
DIについての自由研究内容を発表しました。
Tomohiro Nishimura
March 26, 2017
More Decks by Tomohiro Nishimura
See All by Tomohiro Nishimura
レガシーシステム洗い出し大作戦
sixeight
0
1.7k
まだ見ぬAPIに思いを馳せて
sixeight
0
160
復習OptionSet
sixeight
0
320
今年読んだまんが
sixeight
0
260
べんりな検索ワード
sixeight
0
280
Readable Width in action
sixeight
0
200
UIPreviewInteraction: Overview
sixeight
1
660
Accessing the Music Library
sixeight
1
2.9k
Web APIについての雑談
sixeight
0
420
Other Decks in Programming
See All in Programming
Webの地図
yosuke_furukawa
PRO
6
4k
XHTMLが残したもの
yosuke_furukawa
PRO
2
680
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
150
GKE で Pod の見方を変えたら、スケールアウト時の挙動を真に捉えられた話
stkk
0
110
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
200
MIZARU@SPAJAM2026 第二回予選
1901drama
0
110
AIの中の人になってみる
htkym
0
170
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
3
520
ALB ログから Trace を気合で繋げる技術
fohte
7
880
Security issues being discussed on Web Platforms
petamoriken
0
630
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
140
信頼性の目標を誰も求めてない
shubox
0
500
Featured
See All Featured
From π to Pie charts
rasagy
0
360
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
250
[SF Ruby Conf 2025] Rails X
palkan
2
1.4k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
HDC tutorial
michielstock
2
860
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Are puppies a ranking factor?
jonoalderson
2
3.9k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Utilizing Notion as your number one productivity tool
mfonobong
4
580
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Transcript
զʑ ओޠ͕େ͖͍ ͷ 3FBMNͲ͔͜Βͬ ͯ͘Δͷ͔ 3FBMN8PSME5PVS0TBLB JE4JYFJHIU
ࣗݾհ w JE4JYFJHIU !UPNPIJ@SP ଜ༑༟ w גࣜձࣾͯͳΞϓϦέʔγϣϯΤϯδχΞ w ݄த్ೖࣾ w
ฏຖʮهʯΛॻ͍͍ͯ·͢ w IUUQTJYFJHIUIBUFOBCMPHDPN
ͯͳͰԿΛ͖͔ͬͯͨ αʔϏεએίʔφʔ w .BDLFSFM w IUUQTNBDLFSFMJP w ΧΫϤϜ "1*ɺΞϓϦ
w IUUQTLBLVZPNVKQ w ͯͳϒϩά ΞϓϦ w IUUQIBUFOBCMPHDPNHVJEFBQQ w ͯͳϒοΫϚʔΫ ΞϓϦ w IUUQCIBUFOBOFKQHVJEFBQQ
͓அΓ w 4XJGUͱ+BWB͕ೖΓཚΕ·͢ w J04"OESPJEܦݧऀͷํʹΘΓ͍ͨͱ͍͏ؾ࣋ͪ w ଞͷϓϥοτϑΥʔϜͷํ͝ΊΜͳ͍͞ w ͱ͍͍ͭͭ4XJGUଟΊͰ͢ w
ίʔυΛͤ·͍εϥΠυʹ͓͞ΊΔʹɺදݱྗͷ๛ ͔ͳ4XJGU͕༗ར
3FBMN Ͳ͔͜Βͬͯ͘Δͷ͔
3FBMNΠϯελϯε Ͳ͔͜Βͬͯ͘Δͷ͔
ૉͳํ๏ let realm = try! Realm() Realm realm = Realm.getDefaultInstance();
4XJGU +BWB
͏ͪΐͬͱෳࡶͳྫ let configuration = Realm.Configuration(fileURL: url) let realm = try!
Realm(configuration: configuration) RealmConfiguration configuration = new RealmConfiguration.Builder() .name("data") .build(); Realm realm = Realm.getInstance(configuration); 4XJGU +BWB
Ұൠతͳ$POpHVSBUJPO RealmConfiguration config = new RealmConfiguration.Builder() .name("myrealm.realm") .encryptionKey(getKey()) .schemaVersion(42) .modules(new
MySchemaModule()) .migration(new MyMigration()) .build(); Realm realm = Realm.getInstance(config); +BWB
ઃఆͷΠϯελϯεͲ͜ʹ ࣋ͭͷ͕ྑ͍ͷͩΖ͏͔
ྫ͑4JOHMFUPO class Locator { private static let instance = Locator()
public var realmConfiguration: Realm.Configuration { var configuration = Realm.Configuration() configuration.fileURL = configuration.fileURL! .deletingLastPathComponent() .appendingPathComponent("main.realm") return configuration } } 4XJGU
ઃఆΛ࡞Βͳͯ͘Α͘ͳͬͨ let configuration = Locator.instance.realmConfiguration let realm = try! Realm(configuration:
configuration) RealmConfiguration configuration = Locator.getInstance().getRealmConfig(); Realm realm = Realm.getInstance(configuration); 4XJGU +BWB
3FBMNఏڙͯ͠͠·͏ class Locator { static let instance = Locator() public
var realmConfiguration: Realm.Configuration { return // Realm.ConfigurationΛ࡞Δ } public var realm: Realm { return try! Realm(configuration: realmConfiguration) } } 4XJGU
͔ͳΓ୯७ԽͰ͖ͨ let realm = Locator.instance.realm 4XJGU +BWB Realm realm =
Locator.getInstance().getRealm();
None
<࠶ܝ>-PDBUPS class Locator { static let instance = Locator() public
var realmConfiguration: Realm.Configuration { return // Realm.ConfigurationΛ࡞Δ } public var realm: Realm { return try! Realm(configuration: realmConfiguration) } } 4XJGU
߽՚ͳ-PDBUPS public class Locator { // ɾɾɾུɾɾɾ public RealmConfiguration getRealmConfiguration()
{ … } public Realm getRealm() { … } public APIClient getApiClient() { … } public Tracker getTracker() { … } public UserRepository getUserRepository() { … } public FriendRepository getFriendRepository() { … } public ItemRepository getItemRepository() { … } } +BWB
ͳΜͰ͘ΕΔ܅
4FSWJDF -PDBUPS 1BUUFSO
4FSWJDF-PDBUPS w ͋ΔίϯϙʔωϯτΛ͏ͷʹผͷෳͷί ϯϙʔωϯτ͕ඞཁͳ߹ " # $
4FSWJDF-PDBUPS w ͋Δίϯϙʔωϯτඞཁͳίϯϙʔωϯτ Λ୳ͯ͘͠ΕΔԿ͔͚͍ͩͬͯΕΑ͍ͱ ͍͏͜ͱʹ͢Δ " # $ 4-
ඞཁͳίϯϙʔωϯτΛ ୳ͯ͠ ࡞ͬͯ ͘ΕΔ Կ͔Λ༻ҙ͢Δ
4FSWJDF -PDBUPS 1BUUFSO
ͱ͜ΖͰςετ͍ͨ͠ w ͨͱ͑"1*͔Β+40/Λऔಘͯ͠ɺ3FBMN ʹਖ਼͘͠อଘ͞ΕΔ͔Λ֬ೝ͍ͨ͠
3FQPTJUPSZͷྫ class UserRepository { private let realm = Locator.instance.realm private
let apiClient = Locator.instance.apiClient func load(byID id: String, callback: (User) -> Void) { // APIݺͼग़͠ } private func save(json: [AnyHashable: Any]) { // Realmʹอଘ } } 4XJGU
ࠔΓͦ͏ w ςετͰ͚ͩJONFNPSZͷ3FBMNΛ ͍ͨ͘ͳͬͨΒʁ w "1*ݺͼग़͠Λελϒͨ͘͠ͳͬͨΒʁ
<࠶ܝ>3FQPTJUPSZͷྫ class UserRepository { private let realm = Locator.instance.realm private
let apiClient = Locator.instance.apiClient func load(byID id: String, callback: (User) -> Void) { // APIݺͼग़͠ } private func save(json: [AnyHashable: Any]) { // Realmʹอଘ } } 4XJGU
-PDBUPSΛίϯετϥΫλʹ ͤΔΑ͏ʹ͢Δ public class UserRepository { private final Realm realm;
private final APIClient apiClient; public UserRepository(Locator locator) { realm = locator.getRealm(); apiClient = locator.getApiClient(); } } +BWB
-PDBUPSΛࠩ͠ସ͑ΒΕΔΑ ͏ʹΠϯλʔϑΣʔεʹ͢Δ interface ILocator { RealmConfiguration getRealmConfiguration(); Realm getRealm(); APIClient
getApiClient(); Tracker getTracker(); UserRepository getUserRepository(); FriendRepository getFriendRepository(); ItemRepository getItemRepository(); } +BWB
*-PDBUPSΛίϯετϥΫλʹ ͤΔΑ͏ʹ͢Δ public class UserRepository { private final Realm realm;
private final APIClient apiClient; public UserRepository(ILocator locator) { realm = locator.getRealm(); apiClient = locator.getApiClient(); } } +BWB
.PDL-PDBUPSΛ࡞Δ public class MockLocator implements ILocator { @Override public RealmConfiguration
getRealmConfiguration() { return // in-memory Configuration } @Override public Realm getRealm() { return Realm.getInstance(realmConfiguration()); } @Override public APIClient getApiClient() { return // MockApiClient } @Override public Tracker getTracker() { … } @Override public UserRepository getUserRepository() { … } @Override public FriendRepository getFriendRepository() { … } @Override public ItemRepository getItemRepository() { … } } +BWB
ςετͷ༷ࢠ let locator = MockLocator() let repository = UserRepository(locator) 4XJGU
+BWB Locator locator = new MockLocator(); UserRepository repository = new UserRepository(locator);
ͬͨ͜ͱ w 3FQPTJUPSZ͕ίϯετϥΫλͰ4FSWJDF -PDBUPSΛड͚औΕΔΑ͏ʹͨ͠ w 4FSWJDF-PDBUPSͷΠϯλʔϑΣʔεΛ༻ ҙͯࠩ͠͠ସ͑ΒΕΔΑ͏ʹͨ͠
͜͏ͩͬͨͷ͕ class UserRepository { private let realm: Realm private let
apiClient: APIClient init() { realm = Locator.instance.realm apiClient = Locator.instance.apiClient } } 4XJGU
͜͏ͳΓ·ͨ͠ class UserRepository { private let realm: Realm private let
apiClient: APIClient init(locator: LocatorProtocol) { realm = locator.realm apiClient = locator.apiClient } } 4XJGU
None
<࠶ܝ>.PDL-PDBUPSΛ࡞Δ public class MockLocator implements ILocator { @Override public RealmConfiguration
getRealmConfiguration() { return // in-memory Configuration } @Override public Realm getRealm() { return Realm.getInstance(realmConfiguration()); } @Override public APIClient getApiClient() { return // MockApiClient } @Override public Tracker getTracker() { … } @Override public UserRepository getUserRepository() { … } @Override public FriendRepository getFriendRepository() { … } @Override public ItemRepository getItemRepository() { … } } +BWB
ྫྷ੩ʹߟ͑Δͱʜ w ςετ༻ͷ3FBMNͱ"1*$MJFOU͕ཉ͍ͩ͠ ͚ͩͬͨ w 4FSWJDF-PDBUPSͷΠϯλʔϑΣʔεʹै ͏ͨΊʹͳΜͰ͜ΜͳʹେྔʹίʔυΛॻ͔ ͳ͍ͱ͍͚ͳ͍ͷ͔
զʑ͕ཉ͔ͬͨ͠ͷ protocol UserRepositoryDependency { var realmConfiguration: Realm.Configuration { get }
var realm: Realm { get } var apiClient: APIClient { get } } 4XJGU
ͦͦ3FQPTJUPSZ͕͜ͷ ΠϯλʔϑΣʔεΛड͚औΕ ྑ͔ͬͨͷͰͳ͍͔
͜͏͍͏ײ͡ class UserRepository { private let realm: Realm private let
apiClient: APIClient init(dependency: UserRepositoryDependency) { realm = dependency.realm apiClient = dependency.apiClient } } 4XJGU
Α͘ͳͬͨ.PDL-PDBUPS class MockLocator: UserRepositoryDependency { var realmConfiguration: Realm.Configuration { return
.Configuration(inMemoryIdentifier: "test") } var realm: Realm { return try! Realm(configuration: realmConfiguration) } var apiClient: APIClientProtocol { return new MockApiClient(); } } 4XJGU
4FSWJDF-PDBUPS͜ͷΠϯ λʔϑΣʔεlz࣮͢Δ class Locator: LocatorProtocol, UserRepositoryDependency { var realmConfiguration: Realm.Configuration
{ … } var realm: Realm { … } var apiClient: APIClient { … } var tracker: Tracker { … } var userRepository: UserRepository { … } var friendRepository: FriendRepository { … } var itemRepository: ItemRepository { … } } 4XJGU
࠷ॳͷґଘؔ 6TFS3FQPTJUPSZ -PDBUPS
ΠϯλʔϑΣʔεΛಋೖͨ͋͠ ͱͷґଘؔ 6TFS3FQPTJUPSZ *-PDBUPS -PDBUPS
৽͍͠ґଘؔ 6TFS3FQPTJUPSZ -PDBUPS 6TFS3FTQPTJUPSZ% FQFOEFODZ
ґଘ͕ؔٯసͨ͠
%FQFOEFODZ *OWFSTJPO 1SJODJQMF
ґଘੑٯసͷݪଇ %*1
ґଘੑٯసͷݪଇ %*1 w ্ҐͷϞδϡʔϧԼҐͷϞδϡʔϧʹґଘ ͯ͠ͳΒͳ͍ɻͲͪΒͷϞδϡʔϧʮந ʯʹґଘ͖͢Ͱ͋Δɻ w ʮநʯ࣮ͷৄࡉʹґଘͯ͠ͳΒͳ͍ɻ ࣮ͷৄࡉ͕ʮநʯʹґଘ͖͢Ͱ͋Δɻ
࠷ॳͷґଘؔ 6TFS3FQPTJUPSZ -PDBUPS
%*1 Ұ෦ Λద༻ͨ͠ґଘؔ 6TFS3FQPTJUPSZ *-PDBUPS -PDBUPS
%*1Λద༻ͨ͋͠ͱͷґଘؔ 6TFS3FQPTJUPSZ -PDBUPS 6TFS3FTQPTJUPSZ% FQFOEFODZ
ґଘੑٯసͷݪଇ %*1
ͱ͜ΖͰίϯετϥΫλΛ ͑ͳ͍߹Ͳ͏͢Ε
ΞϓϦ։ൃͰίϯετϥΫλ͕ ͍ʹ͍͘ͱ͜Ζ w J04 w 7JFX$POUSPMMFS w "OESPJE w "DUJWJUZ
w 'SBHNFOU
ߟ͑ΒΕΔํ๏ w ϓϩύςΟʹೖ͢Δ w ηολʔΛ༻ҙ͢Δ w ॳظԽϝιουΛ༻ҙ͢Δ
7JFX$POUSPMMFSͩͱ͜͏͍ ͏͜ͱΛ͠·͢ΑͶ override func prepare(for segue: …) { if let
vc = segue.destination as? NextViewController { vc.locator = Locator.instance } } 4XJGU
ܽ w มߋ͖͢Ͱͳ͍ϓϩύςΟΛ͖ͪΜͱӅṭ Ͱ͖ͳ͍ w ঢ়ଶ͕มΘΔ͔͠Εͳ͍ΦϒδΣΫτͱͷ ΓͱΓۤ௧͕͏
͏Ұ࠷ॳͷ͍ʹΔ
3FBMNΠϯελϯε Ͳ͔͜Βͬͯ͘Δͷ͔
3FBMNΠϯελϯε 4FSWJDF-PDBUPS ͔Βͬͯ͘Δ
7JFX$POUSPMMFS 4FSWJDF-PDBUPSʹ ґଘ͍ͯ͠Δ
͜ͷґଘΛͲ͏ͬͯղܾ͢ Ε͍͍ͷ͔
%FQFOEFODZ *OKFDUJPO 1BUUFSO
https://www.martinfowler.com/articles/injection.html
http://kakutani.com/trans/fowler/injection.html
ґଘΦϒδΣΫτೖ ґଘੑೖ
7JFX$POUSPMMFS 4FSWJDF-PDBUPSʹ ґଘ͍ͯ͠Δ
"#ʹґଘ͍ͯ͠Δ
#"ͷ ґଘ ΦϒδΣΫτ Ͱ͋Δ
ґଘΦϒδΣΫτ %FQFOEFODZ
%FQFOEFODZ ґଘΦϒδΣΫτ *OKFDUJPO ೖ
ೖʁ
ґଘΦϒδΣΫτΛ ඞཁͱ͍ͯ͠Δ ίϯϙʔωϯτʹ͢
Ώ͔͍ͳؒͨͪ w $POTUSVDUPS*OKFDUJPO w 1SPQFSUZ 4FUUFS *OKFDUJPO w *OUFSGBDF*OKFDUJPO w
.FUIPE*OKFDUJPO w BOENPSFʜ
ͳΜ͔ͦ͜͠͏
͖ͬ͞Γ·ͨ͠ΑͶ
$POTUSVDUPS*OKFDUJPO let locator = Locator.instance let repository = UserRepository(locator: locator)
4XJGU +BWB Locator locator = Locator.getInstance(); Repository repository = new UserRepository(locator);
1SPQFSUZ*OKFDUJPO override func prepare(for segue: …) { if let vc
= segue.destination as? NextViewController { vc.locator = Locator.instance } } 4XJGU
ʮґଘΦϒδΣΫτΛ ඞཁͱ͍ͯ͠Δ ίϯϙʔωϯτʹ͢ʯ ͜ͱʹ໊લΛ͚͚ͨͩ
l%FQFOEFODZ*OKFDUJPOJTB EPMMBSUFSNGPSBDFOUDPODFQUz http://www.jamesshore.com/Blog/Dependency- Injection-Demystified.html - James Shore
%FQFOEFODZ ґଘΦϒδΣΫτ *OKFDUJPO ೖ
1SPQFSUZ*OKFDUJPOΛ ফ͍ͨ͠ w ܽ w มߋ͖͢Ͱͳ͍ϓϩύςΟΛ͖ͪΜͱӅ ṭͰ͖ͳ͍ w ঢ়ଶ͕มΘΔ͔͠Εͳ͍ΦϒδΣΫτͱ ͷΓͱΓۤ௧͕͏
ࠓճͷ࡞ઓ w 1SPUPDPM&YUFOTJPO J04 w %*'SBNFXPSL w %BHHFS̉ "OESPJE
w J04σϑΝΫτελϯμʔυ΄͍͠
1SPUPDPM&YUFOTJPO J04 w *OUFSGBDFͷσϑΥϧτ࣮ΛͬͯɺͦΕ Λ࣮͢ΔίϯϙʔωϯτʹґଘΦϒδΣΫ τΛೖ͢Δ w σϑΥϧτϝιου+BWB͔ΒͳͷͰ "OESPJEͰͰ͖ͳ͍
1SPUPDPM&YUFOTJPO protocol WithLocator { var locator: LocatorProtocol { get }
} extension WithLocator { var locator: LocatorProtocol { return Locator.instance } } 4XJGU
1SPUPDPM&YUFOTJPO class RootViewController: UIViewController, WithLocator { override func viewDidAppear(_ animated:
Bool) { super.viewDidAppear(animated) // ຊ userRepository ͑ྑͦ͞͏Ͱ͢Ͷ locator.apiClient.fetchUser(byID: “xxxx”) { [weak self] result in try! locator.realm.write { self?.locator.realm.add(User(json: result.json)) } } } } 4XJGU
ิ w 4FSWJDF-PDBUPS͡Όͳͯ͘ґଘΦϒδΣ ΫτΛೖͯ͠Α͍ w ґଘΛऔಘ͢ΔϓϩύςΟ͕ಥવੜ͑ΔͷͰ ίʔυ͕͍ʹ͘͘ͳΔ
https://speakerdeck.com/yashigani/dependency- injection-in-ios-apps
%BHHFS̉ "OESPJE w (PPHMF੍ͷ%*'SBNFXPSL w $PNQPOFOU͕ґଘπϦʔͷཧ w .PEVMF͕ґଘͷڙڅ 4FSWJDF-PDBUPS
w ͱ͖ͬͭʹ͍͕֮͑͘Δͱґଘཧ͕ͱͯ ָʹͳΔ
"DUJWJUZʹ*OKFDU͢Δ༷ࢠ public class MainActivity extends AppCompatActivity { @Inject Locator mLocator;
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((App) getApplicationContext()) .getApplicationComponent() .newActivityComponentBuilder() .activity(this) .build() .inject(this); } } +BWB
ґଘ͕ଟ͍ͱ public class MainActivity extends AppCompatActivity { @Inject Locator mLocator;
@Inject Realm mRealm; @Inject ApiClient mApiClient; @Inject UserRepository mUserRepository; @Inject FriendRepository mFriendRepository; } +BWB
ิ w ґଘΛϑϨʔϜϫʔΫʹཧͯ͠Β͑Δͱ ָ w 1SPWJEF3FBMNΛJOKFDUͯ͠ผεϨου Ͱ͏ͳͲ؆୯ w %*ͷཧղ͕ඞཁͰɺϑϨʔϜϫʔΫࣗମ ෳࡶͳͷͰɺಋೖ࣌ͷϋʔυϧߴ͍
;Γ͔͑Γ
;Γ͔͑Γ w 4FSWJDF-PDBUPSΛͬͯؾʹ͢Δ͖૬ खΛݶఆ͢Δज़ʹ͍ͭͯ͠·ͨ͠ w *P$%*1ʹ͍ͭͯগ͠৮Ε·ͨ͠ w %*ʹ͍ͭͯ͠·ͨ͠ w ࣮ࡍͷ%*ͷద༻ྫʹ͍ͭͯ͠·ͨ͠
3FBMN Ͳ͔͜Βͬͯ͘Δͷ͔
3FBMN %*ʹΑͬͯ ֎͔Β͖ͬͯ·͢
͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠