Protocol-Oriented Programming in Networking

8889da6a67db3667b0694d993c9a962c?s=47 Yosuke Ishikawa
March 03, 2016
12k

Protocol-Oriented Programming in Networking

8889da6a67db3667b0694d993c9a962c?s=128

Yosuke Ishikawa

March 03, 2016
Tweet

Transcript

  1. PROTOCOL-ORIENTED PROGRAMMING IN NETWORKING ISHKAWA

  2. ISHKAWA?

  3. OVERVIEW PROTOCOL-ORIENTED PROGRAMMING IN NETWORKING 1. Wrapping NSURLSession using protocols

    2. Generic programming on the protocols 3. Combination with RxSwift
  4. TOPIC 1 Wrapping NSURLSession using protocols To make call-site code

    simpler To get responses type-safely
  5. GOAL

  6. GOAL l e t r e q u e s

    t = R e q u e s t ( ) S e s s i o n . s e n d R e q u e s t ( r e q u e s t ) { r e s u l t i n / / r e s u l t : R e s u l t < R e q u e s t . R e s p o n s e , E r r o r > }
  7. GOAL l e t r e q u e s

    t = C r e a t e I s s u e R e q u e s t ( r e p o s i t o r y I D : 1 2 3 , t i t l e : " T e s t " ) S e s s i o n . s e n d R e q u e s t ( r e q u e s t ) { r e s u l t i n / / r e s u l t : R e s u l t < I s s u e , E r r o r > } l e t r e q u e s t = S e a r c h R e p o s i t o r i e s R e q u e s t ( q u e r y : " s w i f t " ) S e s s i o n . s e n d R e q u e s t ( r e q u e s t ) { r e s u l t i n / / r e s u l t : R e s u l t < P a g i n a t i o n R e s p o n s e < R e p o s i t o r y > , E r r o r > } The type of result changes depending on the request type
  8. WHY PROTOCOL? 1. To associate response type with request type

    2. To provide flexible default implementation
  9. WHY PROTOCOL? 1. To associate response type with request type

    2. To provide flexible default implementation
  10. ASSOCIATING RESPONSE TYPE WITH REQUEST TYPE p r o t

    o c o l R e q u e s t T y p e { t y p e a l i a s R e s p o n s e v a r b a s e U R L : N S U R L { g e t } v a r m e t h o d : H T T P M e t h o d { g e t } v a r p a t h : S t r i n g { g e t } v a r p a r a m e t e r s : [ S t r i n g : A n y O b j e c t ] { g e t } f u n c r e s p o n s e F r o m O b j e c t ( o b j e c t : A n y O b j e c t , U R L R e s p o n s e : N S H T T P U R L R e s p o n s e ) t h r o w s - > R e s p o n s e }
  11. ASSOCIATING RESPONSE TYPE WITH REQUEST TYPE c l a s

    s S e s s i o n { . . . f u n c s e n d R e q u e s t < R e q u e s t : R e q u e s t T y p e > ( r e q e u s t : R e q u e s t , h a n d l e r : R e s u l t < R e q u e s t . R e s p o n s e , E r r o r > - > V o i d ) { d o { l e t d a t a : N S D a t a = . . . l e t j s o n : A n y O b j e c t = . . . l e t r e s p o n s e = r e q u e s t . r e s p o n s e F r o m O b j e c t ( j s o n . . . ) h a n d l e r ( . S u c c e s s ( r e s p o n s e ) ) / / R e q u e s t . R e s p o n s e } c a t c h { h a n d l e r ( . F a i l u r e ( e r r o r ) ) } } }
  12. ASSOCIATING RESPONSE TYPE WITH REQUEST TYPE l e t r

    e q u e s t = C r e a t e I s s u e R e q u e s t ( r e p o s i t o r y I D : 1 2 3 , t i t l e : " T e s t " ) S e s s i o n . s e n d R e q u e s t ( r e q u e s t ) { r e s u l t i n / / r e s u l t : R e s u l t < I s s u e , E r r o r > } l e t r e q u e s t = S e a r c h R e p o s i t o r i e s R e q u e s t ( q u e r y : " s w i f t " ) S e s s i o n . s e n d R e q u e s t ( r e q u e s t ) { r e s u l t i n / / r e s u l t : R e s u l t < P a g i n a t i o n R e s p o n s e < R e p o s i t o r y > , E r r o r > } The type of result changes depending on the request type
  13. WHY PROTOCOL? 2. To provide flexible default implementation 1. To

    associate response type with request type
  14. PROVIDING DEFAULT IMPLEMENTATION PART 1: COMMON CONFIGURATIONS p r o

    t o c o l G i t H u b R e q u e s t T y p e : R e q u e s t T y p e { } e x t e n s i o n G i t H u b R e q u e s t T y p e { v a r b a s e U R L : N S U R L { r e t u r n N S U R L ( s t r i n g : " h t t p s : / / a p i . g i t h u b . c o m " ) ! } }
  15. PROVIDING DEFAULT IMPLEMENTATION PART 2: PROTOCOL FOR JSON DECODING s

    t r u c t S e a r c h R e p o s i t o r i e s R e q u e s t : G i t H u b R e q u e s t T y p e { f u n c r e s p o n s e F r o m O b j e c t ( o b j e c t : A n y O b j e c t , U R L R e s p o n s e : N S H T T P U R L R e s p o n s e ) t h r o w s - > R e s p o n s e { g u a r d l e t d i c t i o n a r i e s = o b j e c t a s ? [ [ S t r i n g : A n y O b j e c t ] ] e l s e { t h r o w I n v a l i d O b j e c t ( o b j e c t ) } l e t r e p o s i t o r i e s = d i c t i o n a r i e s . m a p { t r y R e p o s i t o r y ( $ 0 ) } l e t h a s N e x t P a g e = . . . r e t u r n P a g i n a t i o n R e s p o n s e ( e l e m e n t s : r e p o s i t o r i e s , h a s N e x t P a g e : h a s N e x t P a g e ) }
  16. PROVIDING DEFAULT IMPLEMENTATION PART 2: PROTOCOL FOR JSON DECODING p

    r o t o c o l D e c o d a b l e { s t a t i c f u n c d e c o d e ( o b j e c t : A n y O b j e c t ) t h r o w s - > S e l f }
  17. PROVIDING DEFAULT IMPLEMENTATION PART 2: PROTOCOL FOR JSON DECODING e

    x t e n s i o n R e q u e s t T y p e w h e r e R e s p o n s e : D e c o d a b l e { f u n c r e s p o n s e F r o m O b j e c t ( o b j e c t : A n y O b j e c t , U R L R e s p o n s e : N S H T T P U R L R e s p o n s e ) t h r o w s - > R e s p o n s e { r e t u r n R e s p o n s e . d e c o d e ( o b j e c t ) } }
  18. PROVIDING DEFAULT IMPLEMENTATION PART 2: PROTOCOL FOR JSON DECODING s

    t r u c t S e a r c h R e p o s i t o r i e s R e q u e s t : G i t H u b R e q u e s t T y p e { l e t q u e r y : S t r i n g / / M A R K : R e q u e s t T y p e t y p e a l i a s R e s p o n s e = P a g i n a t i o n R e s p o n s e < R e p o s i t o r y > v a r m e t h o d : H T T P M e t h o d { r e t u r n . G E T } v a r p a t h : S t r i n g { r e t u r n " / s e a r c h / r e p o s i t o r i e s " } v a r p a r a m e t e r s : A n y O b j e c t { r e t u r n [ " q " : q u e r y ] } }
  19. WHY PROTOCOL? 1. To associate response type with request type

    Simpler and safer call-site 2. To provide flexible default implementation Documentation-like request definition
  20. LINKS APIKit: RequestType, Session, etc. Himotoki: Decodable, etc. https://github.com/ishkawa/APIKit https://github.com/ikesyo/Himotoki

  21. TOPIC 2 Practical example of generic programming on protocols Example:

    Pagination
  22. PAGINATION REQUEST c u r l - v h t

    t p s : / / a p i . g i t h u b . c o m / s e a r c h / r e p o s i t o r i e s ? q = s w i f t & p a g e = 1
  23. PAGINATION REQUEST p r o t o c o l

    P a g i n a t i o n R e q u e s t T y p e : R e q u e s t T y p e { t y p e a l i a s R e s p o n s e : P a g i n a t i o n R e s p o n s e T y p e v a r p a g e : I n t { g e t } f u n c r e q u e s t W i t h P a g e ( p a g e : I n t ) - > S e l f }
  24. PAGINATION RESPONSE H T T P / 1 . 1

    2 0 0 O K S e r v e r : G i t H u b . c o m C o n t e n t - T y p e : a p p l i c a t i o n / j s o n ; c h a r s e t = u t f - 8 L i n k : < h t t p s : / / a p i . g i t h u b . c o m / . . . > ; r e l = " n e x t " { " t o t a l _ c o u n t " : 3 8 2 6 2 , " i n c o m p l e t e _ r e s u l t s " : f a l s e , " i t e m s " : [ . . . ] }
  25. PAGINATION RESPONSE p r o t o c o l

    P a g i n a t i o n R e s p o n s e T y p e { t y p e a l i a s E l e m e n t : D e c o d a b l e v a r e l e m e n t s : [ E l e m e n t ] { g e t } v a r h a s N e x t P a g e : B o o l { g e t } }
  26. PAGINATION CLIENT c l a s s P a g

    i n a t i o n C l i e n t < R e q u e s t : P a g i n a t i o n R e q u e s t T y p e > { l e t b a s e R e q u e s t : R e q u e s t l e t u p d a t e H a n d l e r : V o i d - > V o i d i n i t ( b a s e R e q u e s t : R e q u e s t , u p d a t e H a n d l e r : V o i d - > V o i d ) { . . . } v a r e l e m e n t s : [ R e q u e s t . R e s p o n s e . E l e m e n t ] v a r h a s N e x t P a g e : B o o l v a r p a g e : I n t f u n c r e f r e s h ( ) { . . . } f u n c l o a d N e x t P a g e ( ) { . . . } }
  27. PAGINATION CLIENT f u n c r e f r

    e s h ( ) { l e t r e q u e s t = b a s e R e q u e s t . r e q u e s t W i t h P a g e ( 1 ) S e s s i o n . s e n d R e q u e s t ( r e q u e s t ) { r e s u l t i n s w i t c h r e s u l t { c a s e . S u c c e s s ( l e t r e s p o n s e ) : s e l f . p a g e = p a g e s e l f . e l e m e n t s = r e s p o n s e . e l e m e n t s s e l f . h a s N e x t P a g e = r e s p o n s e . h a s N e x t P a g e s e l f . u p d a t e H a n d l e r ( ) c a s e . F a i l u r e ( l e t e r r o r ) : / / h a n d l e e r r o r } } }
  28. GENERIC PROGRAMMING ON PROTOCOLS More type constraints, more detailed implementation

  29. TOPIC 3 Advanced example with reactive streams

  30. RXPAGINATION

  31. PAGINATION VM WITH RXSWIFT c l a s s P

    a g i n a t i o n V i e w M o d e l < T : P a g i n a t i o n R e q u e s t T y p e > { i n i t ( b a s e R e q u e s t : T ) { . . . } / / I n p u t l e t r e f r e s h T r i g g e r : P u b l i s h S u b j e c t < V o i d > l e t n e x t P a g e T r i g g e r : P u b l i s h S u b j e c t < V o i d > / / O u t p u t l e t e l e m e n t s : O b s e r v a b l e < [ R e q u e s t . R e s p o n s e . E l e m e n t ] > l e t h a s N e x t P a g e : O b s e r v a b l e < B o o l > l e t l o a d i n g : O b s e r v a b l e < B o o l > }
  32. LIVE!

  33. STEPS TO IMPLEMENT PAGINATION Give a base request to ViewModel

    Bind input and output streams
  34. CONCLUSION PROTOCOL-ORIENTED IN NETWORKING 1. Protocol is a good choice

    for abstraction of networking 2. More type constraints, more detailed implementation 3. Abstraction of event stream is also nice
  35. TRY! POP