Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Leveraging Swift's Type System

Leveraging Swift's Type System

One of the most remarkable qualities of Swift, compared to Objective-C, is its powerful type system. Swift developers have quickly accustomed themselves to the benefits of safer, more expressive APIs.

However, many of us don’t leverage the type system as much as we could. Types can help us eliminate duplicate code, build APIs that are easy to comprehend and even verify a significant portion of our program’s behavior.

This talk will explore how we can leverage the power of Swift’s type system in three broad categories:

1. Code Sharing with Types, via Protocols & Generics
2. Program Verification with Types, including a brief discussion on Types vs. Tests
3. Type First Development

We will discuss how these ideas can be applied in practice by including examples from production apps with large code bases.
Throughout the talk we will also discuss concepts from languages with other type systems and see how they apply to Swift.
Hopefully this talk will inspire the audience to unleash the superpowers of types in their own programs.

Benjamin Encz

August 24, 2016
Tweet

More Decks by Benjamin Encz

Other Decks in Programming

Transcript

  1. Benjamin Encz @benjaminencz 1 — Leveraging Swift's Type System |

    @benjaminencz | 360iDev 2016, August 2016
  2. Leveraging Swift's Type System 2 — Leveraging Swift's Type System

    | @benjaminencz | 360iDev 2016, August 2016
  3. 1. Why Types? 2. Correctness & Documentation via Types 3.

    Code Design with Types 3 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  4. ! Margaret Hamilton with the Apollo 11 code listings /

    NASA P63SPOT3 CA BIT6 # IS THE LR ANTENNA IN POSITION 1 YET EXTEND RAND CHAN33 EXTEND BZF P63SPOT4 # BRANCH IF ANTENNA ALREADY IN POSITION 1 CAF CODE500 # ASTRONAUT: PLEASE CRANK THE TC BANKCALL # SILLY THING AROUND CADR GOPERF1 TCF GOTOP00H # TERMINATE TCF P63SPOT3 # PROCEED SEE IF HE'S LYING P63SPOT4 TC BANKCALL # ENTER INITIALIZE LANDING RADAR CADR SETPOS1 TC POSTJUMP # OFF TO SEE THE WIZARD ... CADR BURNBABY 4 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  5. int a = 2; int b = a; // Copy

    n bytes into a new stack variable ✅ 6 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  6. NSNumber *a = @(2); NSString *c = a; // Incompatible

    pointer types ⚠ [c viewDidLoad]; // No visibile interface declares selector ❌ 7 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  7. NSString *name = nil; NSDictionary *broken = @{@"test": name}; //

    Nil crash! ! 8 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  8. For Each Type a Type System Defines... 1. ... a

    valid set of values 2. ... a valid set of operations 3. ... a representation 9 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  9. (result: NSData?, error: NSError?) // 4 possible combinations ! 13

    — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  10. (result: NSData?, error: NSError?) // 4 possible combinations ! (result:

    Result<Data, NetworkError>) // 2 possible combinations 14 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  11. switch result { case let .success(value): // use success value

    case let .failure(error): // handle error } 15 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  12. public enum Optional<Wrapped> { case none case some(Wrapped) } public

    enum Result<T, Error: Swift.Error> { case success(T) case failure(Error) } 16 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  13. Enums with Associated Values1 ! 1 Formally known as tagged

    unions 17 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  14. // Document semantics of types typealias Address = String typealias

    Email = String struct Person { // ... let email: Email let address: Address } 20 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  15. // Document & validate semantics struct Address { let value:

    String init(addressString: String) throws { // ... } } 21 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  16. github.com/Ben-G/Validated typealias Email = Validated<String, EmailValidator> let maybeEmail = Email("[email protected]")

    22 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  17. Typealias ! Wrapper Types !! 23 — Leveraging Swift's Type

    System | @benjaminencz | 360iDev 2016, August 2016
  18. struct ObjectUid<!> { let value: String } 25 — Leveraging

    Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  19. func currentUserUid() -> ObjectUid<User> func annotationByUid(annotationUid: ObjectUid<Annotation>) -> Annotation func

    annotationsForUser(userUid: ObjectUid<User>) -> [Annotation] 26 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  20. Type Case Study: Modelling JSON Encodable? 27 — Leveraging Swift's

    Type System | @benjaminencz | 360iDev 2016, August 2016
  21. enum JsonRoot { case dictionary(JsonDictionary) case array(JsonArray) } 30 —

    Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  22. protocol JsonValue {} enum JsonRoot: JsonValue { case dictionary(JsonDictionary) case

    array(JsonArray) } extension NSString : JsonValue { } extension NSNumber : JsonValue { } 31 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  23. typealias JsonDictionary = [String : JsonValue?] typealias JsonArray = [JsonValue]

    32 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  24. protocol JsonValue {} typealias JsonDictionary = [String : JsonValue?] typealias

    JsonArray = [JsonValue] enum JsonRoot: JsonValue { case dictionary(JsonDictionary) case array(JsonArray) } extension NSString : JsonValue { } extension NSNumber : JsonValue { } func toJsonString(json: JsonRoot) -> String 34 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  25. Protocols ! Generics 36 — Leveraging Swift's Type System |

    @benjaminencz | 360iDev 2016, August 2016
  26. protocol Downloadable { static var endpoint: URL { get }

    } protocol Decodable { init(data: Data) throws } protocol Cachable { static var cachingDuration: TimeInterval { get } } 40 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  27. final class Downloader<T: Downloadable> { func download(identifier: String) throws ->

    Data { let targetUrl = T.self.endpoint.appendingPathComponent(identifier) // .. return data } } 41 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  28. final class Downloader<T: Downloadable> { func download(identifier: String) throws ->

    Data { let targetUrl = T.self.endpoint.appendingPathComponent(identifier) // ... // Check if this type is cachable if let type = T.self as? Cachable.Type, let cachedResult = cache[targetUrl] { // Attempt to fetch data from cache } // Otherwise download & cache result if type is cachable if T.self is Cachable.Type { cache[targetUrl] = (Date(), data) } return data } } 42 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  29. extension Downloader where T: Decodable { func download(identifier: String) throws

    -> T { let result: Data = try self.download(identifier: identifier) return try T(data: result) } } 43 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  30. extension Photo: Downloadable { static let endpoint = URL(string: "https://photos.example.com")!

    } extension Photo: Cachable { static let cachingDuration: TimeInterval = 3600 } extension Photo: Decodable { static func decode(data: Data) throws -> Photo { // ... } } 44 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  31. let downloader: Downloader<Photo> = Downloader() let photo: Photo = try

    downloader.download(identifier: "hawaii2") 45 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  32. Protocols ! Generics " Safe Dynamic Type Checking ! Constrained

    Extensions ! 46 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  33. ! Types Document ! Types Enable Correctness Checks ! Generics

    Offer Alternative to Subtyping ! Concepts: Optional, Result, Enums with Associated Values, Typealias, Wrapper Types, Phantom Types, Safe Dynamic Type Checking, Constrained Extensions 48 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  34. Thank you! bit.ly/types360 @benjaminencz Thanks a lot to Jaden Geller,

    Russ Bishop and Morgan Chen for feedback on this talk. 49 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016
  35. Related Talks: → Correct Behavior Through Type Safety (Justin Spahr-Summers)

    → Type Driven Development in Swift (Johannas Weiß) → Protocol Oriented Programming in Swift (WWDC 2015) 50 — Leveraging Swift's Type System | @benjaminencz | 360iDev 2016, August 2016