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

potatotips #50: iOSは自動生成の夢を見るか?

potatotips #50: iOSは自動生成の夢を見るか?

Takeshi Ihara

April 09, 2018
Tweet

More Decks by Takeshi Ihara

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • Takeshi Ihara • Recruit Marketing Partners • iOS

    Engineer • Twitter: @nonchalant0303 • GitHub: Nonchalant
  2. Swinject https://github.com/Swinject/Swinject • Swinject helps your app split into loosely-

    coupled components, which can be developed, tested and maintained more easily • Swinject is powered by the Swift generic type system and first class functions to define dependencies of your app simply and fluently
  3. protocol UseCase {} struct UseCaseImpl: UseCase {} let container =

    Container() container.register(UseCase.self) { _ in UseCaseImpl() } let useCase = container.resolve(UseCase.self)!
  4. container.register(A_UseCase.self) { r in A_UseCaseImpl(repository: r.resolve(A_Repository.self)!) } container.register(A_Repository.self) { r

    in A_RepositoryImpl(dataStore: r.resolve(A_DataStore.self)!) } container.register(A_DataStore.self) { _ in A_DataStoreImpl() } … container.register(Z_DataStore.self) { _ in Z_DataStoreImpl() }
  5. container.register(A_UseCase.self) { r in A_UseCaseImpl(repository: r.resolve(A_Repository.self)!) } // container.register(A_Repository.self) {

    r in // A_RepositoryImpl(dataStore: r.resolve(A_DataStore.self)!) // } container.register(A_DataStore.self) { _ in A_DataStoreImpl() } … container.register(Z_DataStore.self) { _ in Z_DataStoreImpl() } ಈత%*ͳͷͰࢀর͞ΕΔ·Ͱؾ͚ͮͳ͍ʂ
  6. Sourcery https://github.com/krzysztofzablocki/Sourcery • Sourcery is a code generator for Swift

    language, built on top of Apple's own SourceKit • It extends the language abstractions to allow you to generate boilerplate code automatically • It uses Stencil as template language
  7. struct UseCaseDependencyInjector: DependencyInjector { func inject(container: Container) { {% for

    interface in types.protocols where interface.name|hasSuffix:"UseCase" %} {% for implement in types.all where implement.name|hasPrefix:interface.name %} container.register({{ interface.name }}.self) { r in {{ implement.name }}( {% for parameter in implement.initializers.first.parameters %} {{ parameter.name }}: r.resolve({{ parameter.typeName }}.self)! {% endfor %} ) } {% endfor %} {% endfor %} } }
  8. // SourceryͷΠϯετʔϧ brew install sourcery // ϑΝΠϧੜ੒ sourcery \ —sources

    Project/UseCase \ —templates UseCase.stencil \ —output .
  9. struct UseCaseDependencyInjector: DependencyInjector { func inject(container: Container) { container.register(A_UseCase.self) {

    _ in A_UseCaseImpl() } container.register(B_UseCase.self) { r in B_UseCaseImpl( repository: r.resolve(B_Repository.self)! ) } … container.register(Z_UseCase.self) { r in Z_UseCaseImpl( repository: r.resolve(Z_Repository.self)! ) } } }