Safer Swift Code with Value Types II (360iDev 2015)

Safer Swift Code with Value Types II (360iDev 2015)

New language, new programming paradigms. Since the release of Swift the Cocoa developer community is increasingly experimenting with functional programming. How can we adopt FP principles in real world applications? This talk will discuss how apps can make use of immutable value types to avoid common code smells and bugs. I will also discuss other benefits of a functional approach, such as modularity through function composition. Throughout the talk I will illustrate the architecture of a non-trivial iOS app that relies strongly on immutable value types. The main goal of this talk is to show pragmatic approaches for applying functional programming principles to common problems in Cocoa development.

This extended version of the talk discusses the Flux architecture used at Facebook and shows how it can be applied to iOS applications built on immutable value types.

De23af005c790b22f8ce4d201e6ca027?s=128

Benjamin Encz

August 16, 2015
Tweet

Transcript

  1. Safer Swift Code with Value Types Safer Swift Code with

    Value Types | @benjaminencz | 360iDev, August 2015 1
  2. What do I mean by safety? Safe, adjective *: -

    involving little or no risk of mishap, error, etc. - dependable or trustworthy * Thanks to Rich Hickey for pointing out this great way to open a talk Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 2
  3. Should I use a struct or a class? It depends!

    4 5 6 7 8 9 9 https://www.mikeash.com/pyblog/friday-qa-2015-07-17-when-to-use-swift-structs-and-classes.html 8 http://owensd.io/2015/07/05/re-struct-or-class.html 7 http://faq.sealedabstract.com/structs_or_classes/: "when it comes time to actually save any of those models to disk, or push them over a network, or draw them to the screen, or whatever, you need a class. Classes everywhere. Not "immutable valuable types everywhere" like in the Struct Philosophy™" 6 Apple Swift Blog: "One of the primary reasons to choose value types over reference types is the ability to more easily reason about your code." 5 Apple Developer Guide: "In practice, this means that most custom data constructs should be classes, not structures" 4 GitHub Styleguide: "Unless you require functionality that can only be provided by a class (like identity or deinitializers), implement a struct instead" Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 3
  4. Agenda 1. What are Value Types vs. Reference Types 2.

    Why is this topic relevant now? 3. How: A Practical Example of a Value Oriented Architecture Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 4
  5. Values vs. References Safer Swift Code with Value Types |

    @benjaminencz | 360iDev, August 2015 5
  6. Reference Types class PersonRefType { let name:String var age:Int //

    .. } // 1 let peter = PersonRefType(name: "Peter", age: 36) // 2 let peter2 = peter // 3 peter2.age = 25 // peter {"Peter", 25} // peter2 {"Peter", 25} Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 6
  7. Value Types struct Person { let name:String var age:Int }

    // 1 let petra = Person(name:"Petra", age:25) // 2 var petra2 = petra // 3 petra2.age = 20 // petra {"Petra", 25} // petra2 {"Petra", 20} Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 7
  8. Why now? Safer Swift Code with Value Types | @benjaminencz

    | 360iDev, August 2015 8
  9. Foundation / C Types Reference Types: - NSArray - NSSet

    - NSData Value Types: - NSInteger - Struct Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 9
  10. Swift Standard Library Reference Types: - ManagedBuffer(?) - NonObjectiveCBase(??) Value

    Types: - Array - String - Optional Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 10
  11. We've Already Been Doing This! @property (copy) NSString *userName; Safer

    Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 11
  12. Case Study A Twitter Client Built on Immutable Value Types

    Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 12
  13. Twitter Client 1. Download the latest 50 tweets and display

    them 2. Allow to filter tweets (RT only, favorited tweets only, etc.) 3. Allow user to favorite tweets (should be synced with server) Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 13
  14. Twitter Client Safer Swift Code with Value Types | @benjaminencz

    | 360iDev, August 2015 14
  15. How can we favorite Tweets? Safer Swift Code with Value

    Types | @benjaminencz | 360iDev, August 2015 15
  16. It Is Very Simple with OOP tweet.favorited = true Safer

    Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 16
  17. It Is Simple with OOP let lockQueue = dispatch_queue_create("com.happysyncing", nil)

    dispatch_sync(lockQueue) { tweet.favorited = true } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 17
  18. Is It Simple with OOP? let lockQueue = dispatch_queue_create("com.happysyncing", nil)

    dispatch_sync(lockQueue) { tweet.favorited = true NSNotificationCenter.defaultCenter(). postNotificationName("Tweet Changed", object: tweet) } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 18
  19. Modeling Change is Hard! let lockQueue = dispatch_queue_create("com.happysyncing", nil) dispatch_sync(lockQueue)

    { tweet.favorited = true NSNotificationCenter.defaultCenter(). postNotificationName("Tweet Changed", object: tweet) tweetAPIClient.markFavorited(tweet.identifier) } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 19
  20. Modeling Change is Hard! — Protect against unwanted updates —

    Distribute new value throughout application — Understand what the underlying identity of an object is and perform update accordingly Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 20
  21. Modeling Change is Hard! — Protect against unwanted updates —

    Distribute new value throughout application — Understand what the underlying identity of an object is and perform update accordingly -> We need to this in all places where we mutate values! Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 21
  22. OOP Data Flow Safer Swift Code with Value Types |

    @benjaminencz | 360iDev, August 2015 22
  23. Is the OOP Data Flow Safe? Safe, adjective: - involving

    little or no risk of mishap, error, etc. - dependable or trustworthy Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 23
  24. Is the OOP Data Flow Safe? Safe, adjective: - involving

    little or no risk of mishap, error, etc. - dependable or trustworthy -> A lot of room for error Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 24
  25. Modelling Change is Hard! Safer Swift Code with Value Types

    | @benjaminencz | 360iDev, August 2015 25
  26. How Can We Model Change With Immutable Value Types? Safer

    Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 26
  27. How Can We Model Change With Immutable Value Types? Model

    change to values as values! Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 27
  28. How Can We Model Change With Immutable Value Types? Model

    change to values as values: — Create a new Tweet for every change Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 28
  29. How Can We Model Change With Immutable Value Types? Model

    change to values as values: — Create a new Tweet for every change — Save these mutations in a local change set Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 29
  30. How Can We Model Change With Immutable Value Types? Model

    change to values as values: — Create a new Tweet for every change — Save these mutations in a local change set — Save the server state in a separate data set Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 30
  31. How Can We Model Change With Immutable Value Types? Model

    change to values as values: — Create a new Tweet for every change — Save these mutations in a local change set — Save the server state in a separate data set — Provide a merged view on list of tweets Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 31
  32. How Can We Model Change With Immutable Value Types? Model

    change to values as values: — Create a new Tweet for every change — Save these mutations in a local change set — Save the server state in a separate data set — Provide a merged view on list of tweets — Provide method to sync local state to server Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 32
  33. Safer Swift Code with Value Types | @benjaminencz | 360iDev,

    August 2015 33
  34. Where do we store state, how is new state distributed?

    Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 34
  35. Where do we store state, how is new state distributed?

    Drawing inspiration from the JavaScript world 11 12: -> Unidirectional Data Flow 12 https://github.com/rackt/redux 11 https://facebook.github.io/flux/ Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 35
  36. Unidirectional data flow Safer Swift Code with Value Types |

    @benjaminencz | 360iDev, August 2015 36
  37. Unidirectional data flow — ActionCreator: Provides interface for business logic

    — Action: Represents an individual state mutation — Dispatcher: Stores state, invokes reducers, publishes new state — Reducers: Pure functions, combine current state and action to produce a new state Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 37
  38. Implementing unidirectional data flow Safer Swift Code with Value Types

    | @benjaminencz | 360iDev, August 2015 38
  39. Representing State — State will be stored in the Dispatcher

    in the following form: typealias TimelineState = (serverState: [Tweet], localState: [Tweet]) typealias TimelineMergedState = (serverState: [Tweet], localState: [Tweet], mergedState: [Tweet]) Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 39
  40. Defining Actions — Each action describes an atomic mutation to

    the application state — Action Creators vend these Actions, Reducers implement them enum Action { case Mount case FavoriteTweet(Tweet) case UnfavoriteTweet(Tweet) //... } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 40
  41. Favoriting a Tweet Within the TimelineViewController we trigger the state

    change by dispatching an Action Creator: func didFavorite(tweetTableViewCell:TweetTableViewCell) { let currentTweet = tweetTableViewCell.tweet! if (currentTweet.isFavorited) { timelineDispatcher.dispatch { TimelineActionCreator.unfavoriteTweet(currentTweet) } } else { timelineDispatcher.dispatch { TimelineActionCreator.favoriteTweet(currentTweet) } } timelineDispatcher.dispatch { TimelineActionCreator.syncFavorites() } } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 41
  42. Favoriting a Tweet Within the TimelineActionCreator we generate an according

    action: static func favoriteTweet(tweet: Tweet) -> ActionCreator { return { state, dispatcher -> Action? in return .FavoriteTweet(tweet) } } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 42
  43. Favoriting a Tweet Within the Reducer we generate a new

    state based on the old one: struct TimelineReducers { //... static func favoriteTweet(var state: TimelineState, tweet: Tweet) -> TimelineState { //... } } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 43
  44. Favoriting a Tweet static func favoriteTweet(var state: TimelineState, tweet: Tweet)

    -> TimelineState { let newTweet = Tweet( content: tweet.content, identifier: tweet.identifier, user: tweet.user, type: tweet.type, favoriteCount: tweet.favoriteCount, isFavorited: true ) let tweetIndex = find(state.localState, tweet) if let tweetIndex = tweetIndex { // if we have stored local state for this tweet previously, override here state.localState[tweetIndex] = newTweet } else { // else append new state state.localState.append(newTweet) } return state } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 44
  45. Favoriting a Tweet Then the Dispatcher forwards the new state

    to its subscribers, which inlcudes the TimelineViewController: extension TimelineViewController: TimelineSubscriber { func newState(state: TimelineMergedState) { // table view is reloaded when 'tweets' is set tweets = state.mergedState } } Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 45
  46. Favoriting a Tweet: Recap Safer Swift Code with Value Types

    | @benjaminencz | 360iDev, August 2015 46
  47. Syncing Change Safer Swift Code with Value Types | @benjaminencz

    | 360iDev, August 2015 47
  48. Syncing Change 1. Iterate over each mutation in the local

    change set Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 48
  49. Syncing Change 1. Iterate over each mutation in the local

    change set 2. Generate API request that syncs that local change to server Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 49
  50. Syncing Change 1. Iterate over each mutation in the local

    change set 2. Generate API request that syncs that local change to server 3. Upon each API response: — If success: remove tweet from local change set — If failure: leave tweet in local change set Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 50
  51. A Twitter Client built on Immutable Value Types Safer Swift

    Code with Value Types | @benjaminencz | 360iDev, August 2015 51
  52. Should I use a struct or a class? It's an

    architectural question! It's not about struct vs. class It's about: - Shared state vs. isolated state - Mutable state vs. immutable state 10 10 WWDC 2014, Session 229, Advanced iOS Application Architecture and Patterns Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 52
  53. Downsides of a Value Oriented Architecture — Unconventional: can be

    an issue when working on larger teams — Can be difficult to integrate with frameworks that rely on reference semantics, e.g. Core Data Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 53
  54. Benefits of a Value Oriented Architecture — Confidence that no

    one will change our data under the covers — State modification & propagation needs to be handled explicitly and can be implemented in one place — Modeling change as data opens opportunities, e.g. simpler client server sync — Easier to test Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 54
  55. The Value Mindset Twitter: @benjaminencz Project & Slides: http://bit.ly/swift-values Related,

    great talks: Controlling Complexity 20, The Value of Values 21 21 http://www.infoq.com/presentations/Value-Values 20 https://realm.io/news/andy-matuschak-controlling-complexity/ Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 55