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
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
地域 SRE コミュニティ最前線 - ホンマでっかSRE勉強会
tk3fftk
0
280
AIが無かった頃の素敵な出会いの話
codmoninc
1
260
Google Apps Script で Ruby を動かす
kawahara
0
110
5分で問診!Composer セキュリティ健康診断
codmoninc
0
670
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
210
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
140
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
3.2k
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
2
140
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
360
使いながら育てる Claude Code — 開発フローの1コマンド化 × 繰り返し指摘の自動仕組み化
shiki_kakaku
0
790
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
250
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
350
Featured
See All Featured
Making Projects Easy
brettharned
120
6.7k
The browser strikes back
jonoalderson
0
1.4k
Context Engineering - Making Every Token Count
addyosmani
9
1k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
250
Are puppies a ranking factor?
jonoalderson
1
3.7k
Writing Fast Ruby
sferik
630
63k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
350
What does AI have to do with Human Rights?
axbom
PRO
1
2.3k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
160
Tell your own story through comics
letsgokoyo
1
1k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
190
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 %*ʹΑͬͯ ֎͔Β͖ͬͯ·͢
͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠