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. 1.

    Safer Swift Code with Value Types Safer Swift Code with

    Value Types | @benjaminencz | 360iDev, August 2015 1
  2. 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. 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. 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. 5.

    Values vs. References Safer Swift Code with Value Types |

    @benjaminencz | 360iDev, August 2015 5
  6. 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. 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. 9.

    Foundation / C Types Reference Types: - NSArray - NSSet

    - NSData Value Types: - NSInteger - Struct Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 9
  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
  10. 11.

    We've Already Been Doing This! @property (copy) NSString *userName; Safer

    Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 11
  11. 12.

    Case Study A Twitter Client Built on Immutable Value Types

    Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 12
  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
  13. 15.

    How can we favorite Tweets? Safer Swift Code with Value

    Types | @benjaminencz | 360iDev, August 2015 15
  14. 16.

    It Is Very Simple with OOP tweet.favorited = true Safer

    Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 16
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 22.

    OOP Data Flow Safer Swift Code with Value Types |

    @benjaminencz | 360iDev, August 2015 22
  21. 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
  22. 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
  23. 25.

    Modelling Change is Hard! Safer Swift Code with Value Types

    | @benjaminencz | 360iDev, August 2015 25
  24. 26.

    How Can We Model Change With Immutable Value Types? Safer

    Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 26
  25. 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
  26. 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
  27. 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
  28. 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
  29. 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
  30. 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
  31. 34.

    Where do we store state, how is new state distributed?

    Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 34
  32. 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
  33. 36.

    Unidirectional data flow Safer Swift Code with Value Types |

    @benjaminencz | 360iDev, August 2015 36
  34. 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
  35. 38.
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. 46.

    Favoriting a Tweet: Recap Safer Swift Code with Value Types

    | @benjaminencz | 360iDev, August 2015 46
  44. 48.

    Syncing Change 1. Iterate over each mutation in the local

    change set Safer Swift Code with Value Types | @benjaminencz | 360iDev, August 2015 48
  45. 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
  46. 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
  47. 51.

    A Twitter Client built on Immutable Value Types Safer Swift

    Code with Value Types | @benjaminencz | 360iDev, August 2015 51
  48. 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
  49. 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
  50. 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
  51. 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