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
我々のRealmはどこからやってくるのか
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Tomohiro Nishimura
March 26, 2017
Programming
440
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
310
今年読んだまんが
sixeight
0
260
べんりな検索ワード
sixeight
0
280
Readable Width in action
sixeight
0
200
UIPreviewInteraction: Overview
sixeight
1
650
Accessing the Music Library
sixeight
1
2.9k
Web APIについての雑談
sixeight
0
420
Other Decks in Programming
See All in Programming
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
400
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
160
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
350
今さら聞けない .NET CLI
htkym
0
140
Prismを使った型安全な暗号化_関数型まつり2026
_fhhmm
0
150
えっ!!コードを読まずに開発を!?
hananouchi
0
270
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
550
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
1
250
ここ半年くらいでAIに作らせたR用ツール
eitsupi
0
320
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
360
自作OSでスライド発表する
uyuki234
1
4k
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
190
Featured
See All Featured
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
330
Prompt Engineering for Job Search
mfonobong
0
380
Exploring anti-patterns in Rails
aemeredith
3
450
Accessibility Awareness
sabderemane
1
160
First, design no harm
axbom
PRO
2
1.2k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
780
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6k
Are puppies a ranking factor?
jonoalderson
1
3.7k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
160
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 %*ʹΑͬͯ ֎͔Β͖ͬͯ·͢
͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠