DI with "Reader Monad"

3925ee6eaa41031bac799de0f4f528ec?s=47 to4iki
March 26, 2018
690

DI with "Reader Monad"

iOS Test Night #7
2018/03/26
https://github.com/to4iki/Reader

3925ee6eaa41031bac799de0f4f528ec?s=128

to4iki

March 26, 2018
Tweet

Transcript

  1. DI with Reader Monad iOS Test Night #7 2018/03/26 @to4iki

    1
  2. Me • Takezawa Toshiki • @to4iki • iOS Engineer •

    ! ☕ ♨ 2
  3. what DI? 3

  4. ֎෦͔Βґଘ(ΦϒδΣΫτ) Λ஫ೖͰ͖ΔΑ͏ʹ͢Δ σβΠϯύλʔϯ 4

  5. ! ϝϦοτ • ίϯϙʔωϯτಉ͕࢜ૄ݁߹ʹͳΔ • I/FΛࢀর͢Δ͜ͱʹͳΔ • ΦϒδΣΫτͷੜ੒ͱ࢖༻͕෼཭͞ΕΔ • ಈ࡞ΛॊೈʹΧελϚΠζͰ͖Δ

    • ґଘ͢ΔΦϒδΣΫτΛࠩ͠ସ͑Δ͜ͱ͕Ͱ͖Δ • -> ςετ͕ॻ͚Δ ! 5
  6. ಈతDI • DI Container ੩తDI • Initializer(Constructor) Injection • Property(Setter)

    Injection • Cake Pattern • Reader Monad 6
  7. Reader Monad 7

  8. ؔ਺Ϟφυ (Input) -> Element ͷϥούʔ struct Reader<Input, Element> { typealias

    WorkFactory = (Input) -> Element private let workFactory: WorkFactory func execute(_ input: Input) -> Element { return workFactory(input) } } 8
  9. map / flatMap func map<T>(_ f: @escaping (Element) -> T)

    -> Reader<Input, T> { return Reader<Input, T> { input in f(self.execute(input)) } } func flatMap<T>(_ f: @escaping (Element) -> Reader<Input, T>) -> Reader<Input, T> { return Reader<Input, T> { input in f(self.execute(input)).execute(input) } } 9
  10. ఆٛ͸͜Μ͚ͩ 10

  11. ex. let plusTwoReader = Reader<Int, Int> { $0 + 2

    } let xxxReader = plusTwoReader .map { $0 * 2 } .map { "value is \($0)" } xxxReader.execute(1) // "value is 6" xxxReader.execute(2) // "value is 8" plusTwoReader .flatMap { x in Reader<Int, Int> { y in x * y } } .execute(3) // 18 11
  12. ධՁ͢Δ·Ͱɺ Πϯϓοτ(ґଘ)Λ ஗Ԇͤ͞Δ͜ͱ͕Ͱ͖Δ 12

  13. Example DI 13

  14. ex. ! protocol UserServiceType { func find(by id: User.Id) ->

    User? } struct UserService: UserServiceType { func find(by id: User.Id) -> User? { ... } } 14
  15. ex. ! Dependency protocol Module { var userService: UserServiceType {

    get } var tweetService: TweetServiceType { get } } 15
  16. ex. ! Client func getTweets(by userId: User.Id) -> Reader<Module, [Tweet]>

    { return Reader { module in module.userService.find(by: userId) .map { $0.name } .map { module.tweetService.findAll(by: $0) } ?? [] } } 16
  17. ex. ! Injection struct ProductionModule: Module { var userService: UserServiceType

    { return UserService.shared } var tweetService: TweetServiceType { return TweetService.shared } } getTweets("prod").execute(ProductionModule()) // [ATweet, BTweet, ...] getTweets("test").execute(MockModule()) // [TestTweet] 17
  18. DI with Reader Monad Pros • ΦϒδΣΫτ୯ҐͰ͸ͳ͘ɺؔ਺୯Ґͷࡉ͔ͳDI͕ग़དྷΔ Cons • ReaderܕʹϩοΫΠϯ͞ΕΔ

    • ೉͍͠ • ґଘ͕ෳ਺ʹͳΔͱѻ͍ʹ͍͘ • Ϟφυ͕ωετͨ࣌͠ͷѻ͍͕৑௕ʹͳΔ 18
  19. Conclusion • DIख๏ͷҰͭʹReader MonadΛ࢖༻ͨ͠ํ๏ ͕͋Δ • SwiftͰѻ͏ʹ͸࣮༻͸ݫ͍͠ҹ৅ • functional-programmingΛಥ͖ਐΊΔڧ ͍ҙࢤͱ֮ޛ͕͋Ε͹...

    • ༷ʑͳDIख๏͕͋Δ͕ɺίϯςΩετ (ϝϯόɾจԽ)ʹԠͨ͡΋ͷΛબ୒͠·͠ΐ͏ʂ 19
  20. https://github.com/ to4iki/Reader 20

  21. Thanks 21