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

Lightweight Dependency Injection tips

Lightweight Dependency Injection tips

Motoki Narita

May 26, 2017
Tweet

More Decks by Motoki Narita

Other Decks in Technology

Transcript

  1. -JHIUXFJHIU%FQFOEFODZ*OKFDUJPOUJQT
    !NPUPLJFF
    QPUBUPUJQT

    View Slide

  2. ࣗݾ঺հ
    w !NPUPLJFF
    w J04ΤϯδχΞ
    w ϝϧΧϦι΢κ΢ॴଐ
    w ϝϧΧϦΧ΢ϧνʔϜ
    w J04%$+BQBOελοϑ

    View Slide

  3. lϝϧΧϦΧ΢ϧzϦϦʔε

    View Slide

  4. View Slide

  5. View Slide

  6. ϦϦʔε͔Β൒݄

    View Slide

  7. w ؤுͬͨߕ൹͋ͬͯɺͷϦϦʔεޙ೔ؒɺ

    ΞϓϦ͸͔ͳΓ҆ఆ͍ͯ͠Δ

    View Slide

  8. w ͍Ζ͍ΖͳऔΓ૊Έ͕ޭΛ૗͍ͯ͠Δ͕ɺͦͷ͏ͪ
    ͷҰ͕ͭ%FQFOEFODZ*OKFDUJPO
    w 88%$ͷ*NQSPWJOH&YJTUJOH"QQTXJUI.PEFSO
    #FTU1SBDUJDFTͱ͍͏ηογϣϯͰ΋%*ʹ͍ͭͯऔ
    Γ্͛ΒΕ͍ͯͯ"QQMF͕ϕετϓϥΫςΟεΛ঺
    հ͍ͯ͠Δ 2JJUBʹ·ͱΊ͍ͯ·͢

    View Slide

  9. IUUQRJJUBDPNNPUPLJFFJUFNTEBEFFD

    View Slide

  10. *NQSPWJOH&YJTUJOH"QQTXJUI.PEFSO#FTU1SBDUJDFT88%$
    IUUQEFWTUSFBNJOHBQQMFDPNWJEFPTXXEDSSUZNHDZZUIWX
    @JNQSPWJOH@FYJTUJOH@BQQT@XJUI@NPEFSO@CFTU@QSBDUJDFTQEG

    View Slide

  11. *NQSPWJOH&YJTUJOH"QQTXJUI.PEFSO#FTU1SBDUJDFT88%$
    IUUQEFWTUSFBNJOHBQQMFDPNWJEFPTXXEDSSUZNHDZZUIWX
    @JNQSPWJOH@FYJTUJOH@BQQT@XJUI@NPEFSO@CFTU@QSBDUJDFTQEG

    View Slide

  12. ͜͜Ͱ঺հ͞Ε͍ͯΔํ๏ͷΑ͘ͳ͍ͱ͜Ζ
    w 4FHVFͰભҠΛߦ͏৔߹ɺ֤ॴͰґଘΦϒδΣΫτ
    Λ౉͢ඞཁ͕͋Δ
    w %3:ʹͳΓʹ͍͘
    w ඞཁͳΦϒδΣΫτΛ౉͞ͳͯ͘΋ίϯύΠϥ͕
    ΤϥʔΛग़ͯ͘͠Εͳ͍
    w ˠҙਤ͠ͳ͍༻్Ͱ࢖ΘΕͨ৔߹ʹɺͰ͖ΔݶΓ
    ίϯύΠϥΤϥʔΛग़͢ίʔυΛॻ͖͍ͨ

    View Slide

  13. ͜͜Ͱ঺հ͞Ε͍ͯΔํ๏ͷΑ͘ͳ͍ͱ͜Ζ
    w 4FHVFͰભҠΛߦ͏৔߹ɺ֤ॴͰґଘΦϒδΣΫτ
    Λ౉͢ඞཁ͕͋Δ
    w %3:ʹͳΓʹ͍͘
    w ඞཁͳΦϒδΣΫτΛ౉͞ͳͯ͘΋ίϯύΠϥ͕
    ΤϥʔΛग़ͯ͘͠Εͳ͍
    w ˠҙਤ͠ͳ͍༻్Ͱ࢖ΘΕͨ৔߹ʹɺͰ͖ΔݶΓ
    ίϯύΠϥΤϥʔΛग़͢ίʔυΛॻ͖͍ͨ

    View Slide

  14. r!@JTILBXB
    lྑ͍ઃܭ͸ޡͬͨ༻๏ΛίϯύΠϧΤϥʔʹ͢Δz

    View Slide

  15. ϝϧΧϦΧ΢ϧͰͷϧʔϧ
    w %*ͳ7JFX$POUSPMMFSΛఆٛͯ͠ɺ7JFX$POUSPMMFSͷ
    ΠϯελϯεԽ͸ίʔυͰߦ͏
    w ը໘ͷϨΠΞ΢τ͸4UPSZCPBSEͰఆٛ͠ɺΠϯε
    λϯεԽͱભҠΛίʔυͰॻ͘

    View Slide

  16. ܦҢ
    w ϝϧΧϦΞοςͷ։ൃΛଓ͚ΔதͰɺʮ4FHVFΛ΍ΊΑ
    ͏ʯͱ͍͏ྲྀΕ͕Ͱ͖ͨ
    w ίʔυΛॻ͖ଓ͚͍ͯ͘தͰݟ͚ͭͨ
    w ϝϧΧϦΞοςͰ͸ը໘ͷભҠʹ4FHVFΛ࢖͍ͬͯͨ
    w ެ։ͨ͘͠ͳ͍ϓϩύςΟΛެ։͢Δඞཁ͕͋ͬͨ
    w ػೳ͕૿͍͑ͯ͘ͱͱ΋ʹԿΛઃఆ͠ͳ͚Ε͹͍͚ͳ
    ͍ͷ͔͕෼͔Βͳ͘ͳΓෳࡶʹͳ͍ͬͯͬͨ

    View Slide

  17. %FQFOEFODZ*OKFDUBCMFQSPUPDPM

    View Slide

  18. ೉͍͜͠ͱ͸͍ͯ͠ͳͯ͘ɺ
    ͜Ε͚ͩ

    View Slide

  19. protocol DependencyInjectable {
    associatedtype Dependency
    static func make(withDependency dependency: Dependency) -> Self
    }

    View Slide

  20. ࢖͍ํ
    %FQFOEFODZ*OKFDUBCMFͳ7JFX$POUSPMMFSͷఆٛํ๏

    View Slide

  21. final class WebViewController: UIViewController, DependencyInjectable {
    private var url: URL!
    typealias Dependency = URL
    static func make(withDependency dependency: Dependency) -> WebViewController {
    let vc = WebViewController.instantiateInitialViewController(with: "WebViewController")
    vc.url = dependency
    return vc
    }
    }
    ґଘ͢ΔΦϒδΣΫτͷఆٛ

    View Slide

  22. final class WebViewController: UIViewController, DependencyInjectable {
    private var url: URL!
    typealias Dependency = URL
    static func make(withDependency dependency: Dependency) -> WebViewController {
    let vc = WebViewController.instantiateInitialViewController(with: "WebViewController")
    vc.url = dependency
    return vc
    }
    }
    %*ͳ7JFX$POUSPMMFSͷΠϯελϯε͸ɺ
    NBLFϝιουͰੜ੒͢Δ

    View Slide

  23. 4FHVFͷ৔߹

    View Slide

  24. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let vc as WebViewController:
    vc.url = url
    default:
    break
    }
    }
    VSMΛ֎෦ʹެ։͢Δඞཁ͕͋Δ
    ͜ͷ7JFX$POUSPMMFSΛݺͼग़͢৔ॴ͕૿͑ͨ৔߹ɺͦͷ౎౓͜ͷίʔυΛ
    ॻ͘ඞཁ͕͋Δ

    View Slide

  25. final class WebViewController: UIViewController, DependencyInjectable {
    private var url: URL!
    typealias Dependency = URL
    static func make(withDependency dependency: Dependency) -> WebViewController {
    let vc = WebViewController.instantiateInitialViewController(with: "WebViewController")
    vc.url = dependency
    return vc
    }
    }
    VSMΛQSJWBUFʹͰ͖Δ
    ΠϯελϯεԽͷํ๏͕౷Ұ͞Ε͍ͯΔ͜ͱͰ%3:ݪଇΛकΕΔ

    View Slide

  26. final class WebViewController: UIViewController, DependencyInjectable {
    private var url: URL!
    typealias Dependency = URL
    static func make(withDependency dependency: Dependency) -> WebViewController {
    let vc = WebViewController.instantiateInitialViewController(with: "WebViewController")
    vc.url = dependency
    return vc
    }
    }
    ͜Ε͚ͩݟΔͱ4FHVFͷํ͕ศརʹݟ͑Δ͕ɺ΋ͬͱෳࡶͳґଘੑ
    Λ஫ೖ͢Δඞཁ͕Ͱ͖ͨ৔߹ʹɺ4FHVFΛ࢖ͬͨํࣜ͸͔ͳΓ໘౗
    ͳ͜ͱʹͳΔ

    View Slide

  27. final class WebViewController: UIViewController, DependencyInjectable {
    private var url: URL!
    private var customUserAgent: String?
    struct Dependency {
    let url: URL
    let customUserAgent: String?
    }
    static func make(withDependency dependency: Dependency) -> WebViewController {
    let vc = WebViewController.instantiateInitialViewController(with: "WebViewController")
    vc.url = dependency.url
    vc.customUserAgent = dependency.customUserAgent
    return vc
    }
    }
    ྫͱͯ͠͸ɺ8FC7JFXʹઃఆ͢ΔDVTUPN6TF"HFOUΛมߋ͢Δඞཁ
    ͕͋Δ৔߹ɺ͜ͷΑ͏ʹ%FQFOEFODZTUSVDUΛఆٛͰ͖ɺNBLFϝ
    ιου಺Ͱ׬݁ͤ͞Δ͜ͱ͕Ͱ͖Δ

    View Slide

  28. ࢖͍ํ
    %FQFOEFODZ*OKFDUBCMFͳ7JFX$POUSPMMFSͷ࢖͍ํ

    View Slide

  29. let vc = WebViewController.make(withDependency: url)
    navigationController?.pushViewController(vc, animated: true)

    View Slide

  30. let vc = WebViewController.make(withDependency: url)
    navigationController?.pushViewController(vc, animated: true)

    View Slide

  31. ຖճNBLF͢Δͷ͕໘౗
    ભҠ͸΄ͱΜͲͷέʔεͰQVTI͔NPEBM
    ˠந৅Խ͍ͨ͠

    View Slide

  32. extension UIViewController {
    func present(viewControllerType: DI.Type, dependency: DI.Dependency,
    withNavigationType navigationType: UINavigationController.Type? = nil, animated: Bool = true,
    completion: (() -> Swift.Void)? = nil) where DI: UIViewController {
    let vc = viewControllerType.make(withDependency: dependency)
    if let navigationType = navigationType {
    let nav = navigationType.init(rootViewController: vc)
    present(nav, animated: animated, completion: completion)
    } else {
    present(vc, animated: animated, completion: completion)
    }
    }
    func push(viewControllerType: DI.Type, dependency: DI.Dependency,
    animated: Bool = true) where DI: UIViewController {
    let vc = viewControllerType.make(withDependency: dependency)
    navigationController?.pushViewController(vc, animated: animated)
    }
    }
    %FQFOEFODZ*OKFDUBCMFΛ࢖ͬͯભҠ࣌ͷίʔυΛந৅Խ

    View Slide

  33. push(viewControllerType: WebViewController.self, dependency: url)
    present(viewControllerType: WebViewController.self,
    dependency: url,
    withNavigationType: CustomNavigationController.self)
    %FQFOEFODZ*OKFDUBCMFϓϩτίϧͷந৅Խͷ͓ӄͰɺ
    ͜Μͳײ͡Ͱָʹॻ͚ΔΑ͏ʹͳͬͨʂ

    View Slide

  34. push(viewControllerType: WebViewController.self, dependency: url)
    present(viewControllerType: WebViewController.self,
    dependency: url,
    withNavigationType: CustomNavigationController.self)
    ͍͖ͳΓ͜͜ʹͨͲΓண͍ͨΘ͚Ͱ͸ͳ͘ɺϦϑΝΫλϦϯάΛ
    ܁Γฦ͍ͯ͘͠தͰ͍·ͷܗʹͳ͍ͬͯͬͨ

    View Slide

  35. ·ͱΊ

    View Slide

  36. ྑ͍ͱ͜Ζ
    w ΠϯελϯεԽͷํ๏͕౷Ұ͞ΕΔ
    w ౷Ұ͞ΕΔ͜ͱʹΑͬͯ%3:ʹ
    w ࠶ར༻ָ͕ʹͳͬͨ
    w ґଘੑ͕ͳ͍6*7JFX$POUSPMMFSͰ΋
    %FQFOEFODZ*OKFDUBCMFʹ͓ͯ͘͜͠ͱʹΑͬ
    ͯɺޙ͔Βґଘੑ͕௥Ճ͞Εͨͱ͖ʹαΫοͱର
    Ԡ͢Δ͜ͱ͕Ͱ͖ΔΑ͏ʹͳͬͨ

    View Slide

  37. ͋Μ·ྑ͘ͳ͍ͱ͜Ζ
    w 4UPSZCPBSEͷ4FHVFΛ࢖Θͳ͍ͱ͍͏બ୒Λͨ͠ͷͰɺ
    4UPSZCPBSEͰը໘ؒͷભҠ͕೺ѲͰ͖ͳ͘ͳͬͨ
    w ˠ$PPSEJOBUPSΫϥεͷΑ͏ͳ΋ͷΛ௥Ճ͢Δ͜ͱͰ
    4UPSZCPBSE্ͰΘ͔Βͳͯ͘΋ίʔυͰՄಡͳঢ়ଶʹ͍ͨ͠
    w ݱঢ়ɺ4UPSZCPBSE͔ΒΠϯελϯεԽ͍ͯ͠Δ෦෼͸4UPSZCPBSE
    ΍Ϋϥε໊͕มߋ͞Εͨͱ͖ʹյΕΔ
    w NBLFͰΠϯελϯεੜ੒Ͱ͖Δ͔ͷςετΛॻ͘͜ͱͰ࠷
    ௿ݶͷΧόʔΛ໨ࢦ͢

    View Slide

  38. ͓ΘΓ

    View Slide