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. iOS͸ࣗಈੜ੒ͷເΛ
    ݟΔ͔ʁ

    5BLFTIJ*IBSB
    QPUBUPUJQT

    View full-size slide

  2. ࣗݾ঺հ
    • Takeshi Ihara
    • Recruit Marketing Partners
    • iOS Engineer
    • Twitter: @nonchalant0303
    • GitHub: Nonchalant

    View full-size slide

  3. Dependency Injection (DI)

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  6. protocol UseCase {}
    struct UseCaseImpl: UseCase {}
    let container = Container()
    container.register(UseCase.self) { _ in
    UseCaseImpl()
    }
    let useCase =
    container.resolve(UseCase.self)!

    View full-size slide

  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()
    }

    View full-size slide

  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()
    }
    ಈత%*ͳͷͰࢀর͞ΕΔ·Ͱؾ͚ͮͳ͍ʂ

    View full-size slide

  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

    View full-size slide

  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 %}
    }
    }

    View full-size slide

  11. // SourceryͷΠϯετʔϧ
    brew install sourcery
    // ϑΝΠϧੜ੒
    sourcery \
    —sources Project/UseCase \
    —templates UseCase.stencil \
    —output .

    View full-size slide

  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)!
    )
    }
    }
    }

    View full-size slide

  13. Summary
    • ϘΠϥʔϓϨʔτίʔυ͸ΨϯΨϯࣗಈੜ੒͠Α͏ʂ
    • ໋໊نଇΛ͔ͳΓར༻͚ͨ͠ͲɺSourcery͸͋Δ
    Protocolʹద߹͍ͯ͠Δܕ͚ͩΛநग़Ͱ͖ΔͷͰ
    Interface, ImplementsͰPrefix͕ͣΕͯͯ΋େৎ෉ͳ͸
    ͣʂ
    • Sourceryʹ͓͚ΔStencilͷจ๏͸ https://github.com/
    SwiftGen/StencilSwiftKit ʹ͋Γ·͢ʂ

    View full-size slide