Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
我々のRealmはどこからやってくるのか
Tomohiro Nishimura
March 26, 2017
Programming
1
260
我々のRealmはどこからやってくるのか
DIについての自由研究内容を発表しました。
Tomohiro Nishimura
March 26, 2017
Tweet
Share
More Decks by Tomohiro Nishimura
See All by Tomohiro Nishimura
レガシーシステム洗い出し大作戦
sixeight
0
920
まだ見ぬAPIに思いを馳せて
sixeight
0
66
復習OptionSet
sixeight
0
170
今年読んだまんが
sixeight
0
190
べんりな検索ワード
sixeight
0
170
Readable Width in action
sixeight
0
110
UIPreviewInteraction: Overview
sixeight
1
520
Accessing the Music Library
sixeight
1
2.2k
Web APIについての雑談
sixeight
0
360
Other Decks in Programming
See All in Programming
Jetpack Compose best practices 動画紹介 @GoogleI/O LT会
takakitojo
0
320
How we run a Realtime Puzzle Fighting Game on AWS Serverless
falken
0
250
Reactive Java Microservices on Kubernetes with Spring and JHipster
deepu105
1
170
[DevTrends - Jun/2022] Arquitetura baseada em eventos
camilacampos
0
150
Jetpack Composeでの画面遷移
iwata_n
0
120
GitHubのユーザー名を変更した後のあれこれ
tahia910
0
130
Overview of The Modern Data Stack / モダンデータスタック概論
satoshihirose
6
3.3k
Deep Dive Into Google Zanzibar and its Concepts for Authorization Scenarios
dschenkelman
1
120
Client-Side Field-Level Encryption for Apache Kafka Connect @ VoxxedDays Luxembourg 2022
hpgrahsl
0
110
ES2022の新機能
smt7174
0
240
チームでカレーを作ろう!アジャイルカレークッキング
akitotsukahara
0
800
VisualProgramming_GoogleHome_LINE
nearmugi
1
220
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
780
250k
Building an army of robots
kneath
299
40k
Building a Scalable Design System with Sketch
lauravandoore
448
30k
Writing Fast Ruby
sferik
612
57k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
19
1.4k
Art, The Web, and Tiny UX
lynnandtonic
280
17k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
105
16k
Keith and Marios Guide to Fast Websites
keithpitt
404
21k
Making the Leap to Tech Lead
cromwellryan
113
7.4k
Designing Experiences People Love
moore
130
22k
Intergalactic Javascript Robots from Outer Space
tanoku
261
25k
The Invisible Customer
myddelton
110
11k
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 %*ʹΑͬͯ ֎͔Β͖ͬͯ·͢
͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠