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

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

D390d62a9772cf2e0bd8000157abbff8?s=128

Takeshi Ihara

April 09, 2018
Tweet

Transcript

  1. iOS͸ࣗಈੜ੒ͷເΛ ݟΔ͔ʁ  5BLFTIJ*IBSB QPUBUPUJQT

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

    Engineer • Twitter: @nonchalant0303 • GitHub: Nonchalant
  3. Dependency Injection (DI)

  4. DI Library • DIKit • Swinject • Typhoon • Cleanse

  5. 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
  6. protocol UseCase {} struct UseCaseImpl: UseCase {} let container =

    Container() container.register(UseCase.self) { _ in UseCaseImpl() } let useCase = container.resolve(UseCase.self)!
  7. 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() }
  8. 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() } ಈత%*ͳͷͰࢀর͞ΕΔ·Ͱؾ͚ͮͳ͍ʂ
  9. 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
  10. 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 %} } }
  11. // SourceryͷΠϯετʔϧ brew install sourcery // ϑΝΠϧੜ੒ sourcery \ —sources

    Project/UseCase \ —templates UseCase.stencil \ —output .
  12. 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)! ) } } }
  13. Summary • ϘΠϥʔϓϨʔτίʔυ͸ΨϯΨϯࣗಈੜ੒͠Α͏ʂ • ໋໊نଇΛ͔ͳΓར༻͚ͨ͠ͲɺSourcery͸͋Δ Protocolʹద߹͍ͯ͠Δܕ͚ͩΛநग़Ͱ͖ΔͷͰ Interface, ImplementsͰPrefix͕ͣΕͯͯ΋େৎ෉ͳ͸ ͣʂ •

    Sourceryʹ͓͚ΔStencilͷจ๏͸ https://github.com/ SwiftGen/StencilSwiftKit ʹ͋Γ·͢ʂ