Slide 1

Slide 1 text

!ZPJDIJUHZ Practical Structure to Configure Dependency Injection in iOS/Swift Yoichi Tagaya Swift & Fika, 10 September, 2018

Slide 2

Slide 2 text

!ZPJDIJUHZ Yoichi Tagaya, from Tokyo, Japan About me

Slide 3

Slide 3 text

!ZPJDIJUHZ Tokyo evening view 1IPUPCZ D 5PNP:VO IUUQXXXZVOQIPUPOFU

Slide 4

Slide 4 text

!ZPJDIJUHZ About me as Swinject author • Swinject: dependency injection framework for Swift • Maintained by 5 members • Recently by Jakub Vano especially! • 2,6k+ GitHub stars now and 1k clones everyday • 4 extensions provided

Slide 5

Slide 5 text

!ZPJDIJUHZ Agenda • Software architecture • Dependency injection (DI) • Swinject (DI container)

Slide 6

Slide 6 text

!ZPJDIJUHZ What is software architecture

Slide 7

Slide 7 text

!ZPJDIJUHZ What is software architecture IUUQTXXXJCNDPNEFWFMPQFSXPSLTSBUJPOBMMJCSBSZGFCFFMFTJOEFYIUNM

Slide 8

Slide 8 text

!ZPJDIJUHZ Peter Eeles says An architecture • Defines structure and behavior • Focuses on significant elements • May conform to an architectural style • Influences team structure (inverse Conway maneuver) • Balances stakeholder needs • Is influenced by its environment • Embodies decisions based on rationale

Slide 9

Slide 9 text

!ZPJDIJUHZ Architecture is not static but dynamic .7$ "SDIJUFDUVSF :FBST TJODFMBVODI .77. 7*1&3 &YBNQMFPGBQSPEVDU 3*#T &OHJOFFST 6TFST L . .

Slide 10

Slide 10 text

!ZPJDIJUHZ Architecture is not static but dynamic $ # " /PX

Slide 11

Slide 11 text

!ZPJDIJUHZ Architecture is not static but dynamic $ # " /PX $ /FX# " $ % -BUFS

Slide 12

Slide 12 text

!ZPJDIJUHZ Production / unit test $ # " 1SPEVDUJPO

Slide 13

Slide 13 text

!ZPJDIJUHZ Production / unit test $ # " 1SPEVDUJPO 6OJU5FTU .PDLTUVC PG# "

Slide 14

Slide 14 text

!ZPJDIJUHZ We need flexibility in architecture

Slide 15

Slide 15 text

!ZPJDIJUHZ How to make architecture flexible? Dependency injection!

Slide 16

Slide 16 text

!ZPJDIJUHZ Because dependency injection is glue but sticky-like glue 5JHIU$PVQMJOH -PPTF$PVQMJOH

Slide 17

Slide 17 text

!ZPJDIJUHZ How to make the sticky-like glue?

Slide 18

Slide 18 text

!ZPJDIJUHZ SOLID principles • S - Single responsibility principle • O - Open/closed principle • L - Liskov substitution principle • I - Interface segregation principle • D - Dependency inversion principle • Should not depend on concretions but abstractions

Slide 19

Slide 19 text

!ZPJDIJUHZ Depending on concretions / abstractions Depending on concretions (tight coupling) *NQMFNFOUBUJPO $PODSFUF5ZQF Depending on abstractions (loose coupling) 3FGFSFODF *NQMFNFOUBUJPO Protocol (Interface) 3FGFSFODF $PODSFUF5ZQF" $PODSFUF5ZQF#

Slide 20

Slide 20 text

!ZPJDIJUHZ Dependency injection: a way to realize dependency inversion principle *NQMFNFOUBUJPO Protocol (Interface) 3FGFSFODF *OTUBODFPG $PODSFUF5ZQF# 1BTT JOKFDU UPJOJUJBMJ[FS $PODSFUF5ZQF# 5IFTZTUFNJTDPOpHVSFE UPVTF$PODSFUF5ZQF#

Slide 21

Slide 21 text

!ZPJDIJUHZ Code example of dependency injection protocol APIClientProtocol { ... } class APIClient: APIClientProtocol { ... } let vm = MyViewModel(apiClient: APIClient()) class MyViewModel { let apiClient: APIClientProtocol init(apiClient: APIClientProtocol) { self.apiClient = apiClient } } APIClientProtocol "CTUSBDUUZQF *OKFDUDPODSFUFUZQF

Slide 22

Slide 22 text

!ZPJDIJUHZ Try dependency injection with Swinject Register/resolve-style DI container like dictionary

Slide 23

Slide 23 text

!ZPJDIJUHZ How to use Swinject container $POUBJOFS Register Resolve

Slide 24

Slide 24 text

!ZPJDIJUHZ Code example of registration $POUBJOFS Register import Swinject let container = Container() container.register(MyViewModel.self) { resolver in let apiClient = resolver.resolve(APIClientProtocol.self)! return MyViewModel(apiClient: apiClient) } container.register(APIClientProtocol.self) { _ in APIClient() }

Slide 25

Slide 25 text

!ZPJDIJUHZ Code example of resolution $POUBJOFS Resolve import Swinject let vm = container.resolve(MyViewModel.self)!

Slide 26

Slide 26 text

!ZPJDIJUHZ It’s ok for a simple case, but…

Slide 27

Slide 27 text

!ZPJDIJUHZ In a production app class MyViewModel { init(dep1: D1, dep2: D2, dep3: D3, id: String, name: String) { ... } } .BOZEFQFOEFODJFT 3VOUJNFQBSBNFUFST PUIFSUIBOEFQFOEFODJFT %FQFOEFODZJOKFDUJPODPEFJTPGUFOMJLFUIJT

Slide 28

Slide 28 text

!ZPJDIJUHZ Using typealias of dependency tuple init(dependency: Dependency, id: String, name: String) 5ZQFBMJBTPGUVQMF % % % %FQFOEFODZ 1BSBNFUFST

Slide 29

Slide 29 text

!ZPJDIJUHZ Example of class definition with typealias of tuple protocol APIClientProtocol { ... } class APIClient: APIClientProtocol { ... } protocol LoggerProtocol { ... } class Logger: LoggerProtocol { ... } 5ZQFBMJBTPG EFQFOEFODZUVQMF class MyViewModel { typealias Dependency = ( APIClientProtocol, LoggerProtocol ) let (apiClient, logger): Dependency let id: String init(dependency: Dependency, id: String) { (apiClient, logger) = dependency self.id = id } } &YBNQMFXJUIEFQFOEFODJFTBOEQBSBNFUFS

Slide 30

Slide 30 text

!ZPJDIJUHZ DI Registration let container = Container() container.register(APIClientProtocol.self) { _ in APIClient() } container.register(LoggerProtocol.self) { _ in Logger() } $POUBJOFS Register container.register(MyViewModel.self) { (resolver, id: String) in let dependency = ( resolver.resolve(APIClientProtocol.self)!, resolver.resolve(LoggerProtocol.self)! ) return MyViewModel( dependency: dependency, id: id ) }

Slide 31

Slide 31 text

!ZPJDIJUHZ DI Resolution let myViewModel = container.resolve( MyViewModel.self, argument: "abc")! $POUBJOFS Resolve

Slide 32

Slide 32 text

!ZPJDIJUHZ Good to evolve the system

Slide 33

Slide 33 text

!ZPJDIJUHZ Summary • Architecture is not static but dynamic to evolve. • Dependency injection is sticky-like glue. • Use a typealias to group dependencies.

Slide 34

Slide 34 text

!ZPJDIJUHZ More info, thanks! • Swinject Tutorial for iOS: Getting Started by Gemma Barlow at raywenderlich.com • iOS App Development: Design Patterns for Mobile Architecture by Jon Bott at lynda.com • Dependency injection in Swift by Manuel Munoz at blog.quadiontech.com • Adventures in Dependency Swinjection by Ben Dietzkis at medium.com/@topLayoutGuide • Swinject - Dependency Injection in iOS by Iron Ben Zvi at speakerdeck.com/oronbz