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
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Tomohiro Nishimura
March 26, 2017
Programming
430
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
270
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
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
2
380
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
520
Modding RubyKaigi for Myself
yui_knk
0
910
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
250
Why Laravel apps break—Mastering the fundamentals to keep them maintainable
kentaroutakeda
1
350
CSC307 Lecture 17
javiergs
PRO
0
320
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
150
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
320
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
160
運用エージェントは "作る" から "育てる" へ - 記憶と自己進化の3層設計パターン / self-evolving-agents-three-layer-agent-design
gawa
12
3.6k
Contextとはなにか
chiroruxx
0
280
A2UI という光を覗いてみる
satohjohn
1
120
Featured
See All Featured
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
190
Docker and Python
trallard
47
3.9k
Being A Developer After 40
akosma
91
590k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
22k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.2k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
The Cost Of JavaScript in 2023
addyosmani
55
10k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
530
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 %*ʹΑͬͯ ֎͔Β͖ͬͯ·͢
͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠