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
Static Dependency Injection by Code Generation
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Yosuke Ishikawa
September 17, 2017
Technology
6.8k
15
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Static Dependency Injection by Code Generation
Yosuke Ishikawa
September 17, 2017
More Decks by Yosuke Ishikawa
See All by Yosuke Ishikawa
効率的な開発手段として VRTを活用する
ishkawa
1
250
アプリを起動せずにアプリを開発して品質と生産性を上げる
ishkawa
0
4.6k
Achieving Testability in Presentation Layer
ishkawa
4
3.9k
Introducing Wire: Dependency Injection by Code Generator
ishkawa
12
1.4k
Declarative UICollectionView
ishkawa
28
8.5k
Nuxt.jsが掲げる"Universal Vue.js Applications"とは何者か
ishkawa
10
2.8k
実践クライアントサイドSwift
ishkawa
23
4.4k
JSON-RPC on APIKit
ishkawa
5
68k
RxSwiftは開発をどう変えたか?
ishkawa
12
4.2k
Other Decks in Technology
See All in Technology
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
1.9k
[モダンアプリ勉強会]今更聞けないGit/GitHub入門
tsukuboshi
0
290
ChatworkとBPaaS 異なる特性で学んだAI機能開発の ベストプラクティス
kubell_hr
2
3k
タクシーアプリ『GO』の実践的データ活用
mot_techtalk
3
170
Claude Codeを組織で使いこなす— サーバサイドAIエージェント運用の実践知
techtekt
PRO
0
210
サイバーセキュリティ概論 / Introduction to Cybersecurity
ks91
PRO
0
170
Amazon Bedrock AgentCore ワークショップ JAWS UG TOHOKU / amazon-bedrock-agentcore-workshop-jawsug-tohoku-2026
gawa
8
390
コードレビューを制するチームがソフトウェアデリバリーのフローを制す / Beyond Code Review: Distributing Its Responsibilities Across the SDLC
mtx2s
4
1.2k
速さだけじゃない! VoidZero ツールが移行先に選ばれる理由
mizdra
PRO
6
760
製造業のクラウド活用最適解〜AI,DXを加速するデータ基盤の作り方〜
hamadakoji
0
400
ABEMA の Datadog × OTel 基盤、 中から見るか? 外から見るか?
tetsuya28
0
110
AI Testing Talks: Challenges of Applying AI in Software Testing: From Hype to Practical Use
exactpro
PRO
1
140
Featured
See All Featured
Technical Leadership for Architectural Decision Making
baasie
3
400
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
[SF Ruby Conf 2025] Rails X
palkan
2
1.1k
Documentation Writing (for coders)
carmenintech
77
5.4k
KATA
mclloyd
PRO
35
15k
Bash Introduction
62gerente
615
210k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.7k
Google's AI Overviews - The New Search
badams
0
1k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
130
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
360
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
Transcript
コード生成による 静的な Dependency Injection
None
None
Dependency Injection(DI) の概要 DI をサポートする仕組みがなぜ必要か コード生成による静的なDI
DI = Dependency Injection
DI = 必要なものを外から渡す Dependency: 必要なもの Injection: 外から渡す
final class ImageDownloader { private let urlSession = URLSession.shared func
downloadImage(with url: URL, completion: (UIImage) -> Void) { let task = urlSession.dataTask(with: url) {...} task.resume() } }
final class ImageDownloader { private let urlSession: URLSession init(urlSession: URLSession)
{ self.urlSession = urlSession } func downloadImage(with url: URL, completion: (UIImage) -> Void) { let task = urlSession.dataTask(with: url) {...} task.resume() } }
dependency の切り替えが可能 dependency の詳細を必要以上に決めずに済む
IoC: Inversion of Control DIP: Dependency Inversion Principle
デメリットはあるの?
dependency の切り替えが可能 dependency の詳細を必要以上に決めずに済む
dependency のインスタンスを取得して渡す責務が外側に生じる
None
DI なし: 密結合だがインスタンスの生成は簡単 DI あり: 疎結合だがインスタンスの生成が面倒
DI なし: 密結合だがインスタンスの生成は簡単 DI あり: 疎結合だがインスタンスの生成が面倒 ???: 疎結合だしインスタンスの生成が簡単
DI をサポートする仕組み
右側のインスタンスの取得を自動化する
自動的にインスタンスを生成できる型を 方法とセットで登録しておく
インスタンスを自動的に取得する方法 DI 用のinitializer を登録する DI 用のprovider method を用意する
final class APIClient { @Inject APIClient(urlSession: URLSession, cache: Cache) {
... } } Dagger のDI 用のconstructor(Java)
None
provider method = インスタンスを提供するメソッド
@Module final class APIModule { @Provides static APIClient provideAPIClient(urlSession: URLSession,
cache: Cache) ... } } Dagger のDI 用のprovider method(Java)
各ノードの定義ができるようになった
グラフの生成
None
@Generated public final class DaggerAPIComponent implements APIComponent { private Provider<URLSession>
urlSessionProvider; private Provider<Cache> cacheProvider; private Provider<APIClient> apiClientProvider; private void initialize() { urlSessionProvider = ... cacheProvider = ... apiClientProvider = APIModule_APIClientFactory .create(urlSessionProvider, cacheProvider); } @Override public APIClient apiClient() { return apiClientProvider.get() } } 生成されたコードで依存関係の解決を表現(Java)
Swi での実践
DI に使用できるinitializer の定義 DI に使用できるprovider method の定義 コード生成による依存関係の解決
DI に使用できるinitializer
final class APIClient { @Inject APIClient(urlSession: URLSession, cache: Cache) {
... } } Dagger のDI 用のconstructor(Java)
protocol Injectable { associatedtype Dependency init(dependency: Dependency) } final class
APIClient: Injectable { struct Dependency { let urlSession: URLSession let cache: Cache } init(dependency: Dependency) {...} } Swi のDI 用のinitializer
DI に使用できるprovider method
@Module final class APIModule { @Provides static APIClient provideAPIClient(urlSession: URLSession,
cache: Cache) ... } } Dagger のDI 用のprovider method(Java)
protocol Resolver {}
protocol AppResolver: Resolver { func provideURLSession() -> URLSession func provideCache()
-> URLSession func provideAPIClient(urlSession: URLSession, cache: Cache) -> APIClient } Swi のDI 用のprovider method
依存関係を解決するコード生成
記述されているコードを解釈して、それを補完するコードを生成
SourceKitten
{ "key.accessibility" : "source.lang.swift.accessibility.internal", "key.kind" : "source.lang.swift.decl.struct", "key.name" : "A",
"key.inheritedtypes" : [ { "key.name" : "Injectable" } ] }
Resolver のprotocol extension に インスタンスを取得するメソッドを生やす
struct A: Injectable { struct Dependency { let b: B
} init(dependency: Dependency) {} } struct B {} protocol ABResolver: Resolver { func provideB() -> B }
extension ABResolver { func resolveA() -> A { let b
= resolveB() return A(dependency: .init(b: b)) } func resolveB() -> B { return provideB() } } provideB() の実装はABResolver の準拠側に委ねられる
final class AppABResolver { func provideB() { return B() }
}
None
プロトコルにした意味は? どう提供するかは決めていない状態でグラフを組める 必要なものが揃っていることがコンパイル時に保証される
自動的に取得できないdependency は?
すべてのdependency が自動的に解決できるものとは限らない ↓ resolve メソッドのパラメーターとして渡す必要がある場合もある
final class UserProfileViewController: UIViewController, Injectable { struct Dependency { let
userID: Int64 let apiClient: APIClient } init(dependency: Dependency) {} } final class APIClient {...} protocol AppResolver: Resolver { func provideAPIClient() -> APIClient }
extension AppResolver { func resolveAPIClient() -> APIClient { return provideAPIClient()
} func resolveUserProfileViewController(userID: Int64) -> UserProfileViewContr let apiClient = resolveAPIClient() return UserProfileViewController(dependency: .init(userID: userID, apiCl } }
None
デモ
https://github.com/ishkawa/DIKit