Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Static Dependency Injection by Code Generation

Yosuke Ishikawa
September 17, 2017

Static Dependency Injection by Code Generation

Yosuke Ishikawa

September 17, 2017
Tweet

More Decks by Yosuke Ishikawa

Other Decks in Technology

Transcript

  1. final class ImageDownloader { private let urlSession = URLSession.shared func

    downloadImage(with url: URL, completion: (UIImage) -> Void) { let task = urlSession.dataTask(with: url) {...} task.resume() } }
  2. 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() } }
  3. @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)
  4. 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
  5. protocol AppResolver: Resolver { func provideURLSession() -> URLSession func provideCache()

    -> URLSession func provideAPIClient(urlSession: URLSession, cache: Cache) -> APIClient } Swi のDI 用のprovider method
  6. struct A: Injectable { struct Dependency { let b: B

    } init(dependency: Dependency) {} } struct B {} protocol ABResolver: Resolver { func provideB() -> B }
  7. extension ABResolver { func resolveA() -> A { let b

    = resolveB() return A(dependency: .init(b: b)) } func resolveB() -> B { return provideB() } } provideB() の実装はABResolver の準拠側に委ねられる
  8. 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 }
  9. extension AppResolver { func resolveAPIClient() -> APIClient { return provideAPIClient()

    } func resolveUserProfileViewController(userID: Int64) -> UserProfileViewContr let apiClient = resolveAPIClient() return UserProfileViewController(dependency: .init(userID: userID, apiCl } }