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

GraphQL From The Ground Up - SoftGeeks, Online, October 2020

GraphQL From The Ground Up - SoftGeeks, Online, October 2020

Video: https://www.youtube.com/watch?v=8YplqeZ2BYA

Abstract: You've heard a lot of people talking about GraphQL lately, but what IS it? What are the problems it's supposed to be solving - and what are the problems it's _not_ supposed to be solving? How can you use it to improve your iOS development process? Ellen Shapiro, who maintains the Apollo GraphQL iOS SDK, will help untangle all this and more.

Ellen Shapiro
PRO

October 21, 2020
Tweet

More Decks by Ellen Shapiro

Other Decks in Technology

Transcript

  1. GRAPHQL FROM THE GROUND UP
    SOFTGEEKS | THE INTERNETS | OCTOBER 2020
    ELLEN SHAPIRO | @DESIGNATEDNERD | APOLLOGRAPHQL.COM

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. WTF IS GRAPHQL?

    View Slide

  6. View Slide

  7. WHAT IS A GRAPH?

    View Slide

  8. View Slide

  9. WHAT IS A GRAPH?
    (WHEN WE TALK ABOUT GRAPHQL)

    View Slide

  10. !
    GRAPH THEORY

    View Slide

  11. In computer science, graphs are used to represent networks of
    communication, data organization, computational devices, the flow of
    computation, etc.
    https://en.wikipedia.org/wiki/Graph_theory#Computer_science

    View Slide

  12. View Slide

  13. Source: https://neo4j.com/blog/graph-theory-predictive-modeling/

    View Slide

  14. Source: https://neo4j.com/blog/graph-theory-predictive-modeling/

    View Slide

  15. Source: https://neo4j.com/blog/graph-theory-predictive-modeling/

    View Slide

  16. Source: https://neo4j.com/blog/graph-theory-predictive-modeling/

    View Slide

  17. DIRECTED GRAPH
    Source: https://neo4j.com/blog/graph-theory-predictive-modeling/

    View Slide

  18. View Slide

  19. UNDIRECTED GRAPH

    View Slide

  20. NODES
    INDIVIDUAL PIECES OF DATA

    View Slide

  21. EDGES
    RELATIONSHIPS BETWEEN PIECES OF DATA

    View Slide

  22. View Slide

  23. SO IS A RELATIONAL DATABASE A GRAPH?
    !

    View Slide

  24. NOT QUITE.

    View Slide

  25. View Slide

  26. View Slide

  27. View Slide

  28. View Slide

  29. RELATIONAL DATABASES ARE FOCUSED ON
    SINGLE RELATIONSHIPS

    View Slide

  30. GRAPHS HELP YOU TO TRACK
    MANY RELATIONSHIPS

    View Slide

  31. user.father.bestFriend.children[0].middleName

    View Slide


  32. GRAPHQL!

    View Slide

  33. GRAPH QUERY LANGUAGE

    View Slide

  34. HOW DO I GRAPHQL?

    View Slide

  35. SAMPLE SERVER
    HTTPS://APOLLO-FULLSTACK-TUTORIAL.HEROKUAPP.COM/

    View Slide

  36. THE SCHEMA

    View Slide

  37. THE SCHEMA
    WHAT IS IT POSSIBLE TO ASK FOR?

    View Slide

  38. SCHEMA DEFINITION LANGUAGE

    View Slide

  39. SCHEMA DEFINITION LANGUAGE
    (BASICALLY, TYPESCRIPT)

    View Slide

  40. View Slide

  41. View Slide

  42. View Slide

  43. View Slide

  44. SCALAR TYPES

    View Slide

  45. SCALAR TYPES
    THE BUILDING BLOCKS OF THE TYPE SYSTEM

    View Slide

  46. OPTIONALS?!

    View Slide


  47. POP QUIZ!

    View Slide

  48. Q. IS THIS TYPE OPTIONAL?

    View Slide

  49. Q. IS THIS TYPE OPTIONAL?
    String

    View Slide

  50. Q. IS THIS TYPE OPTIONAL?
    String
    A: IT DEPENDS

    View Slide

  51. View Slide

  52. View Slide

  53. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE

    View Slide

  54. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No

    View Slide

  55. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No String

    View Slide

  56. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No String String!

    View Slide

  57. !

    View Slide

  58. GRAPHQL TYPES ARE
    NULLABLE BY DEFAULT

    View Slide

  59. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No String String!

    View Slide

  60. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No String String!
    Yes

    View Slide

  61. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No String String!
    Yes String?

    View Slide

  62. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE
    No String String!
    Yes String? String

    View Slide

  63. View Slide

  64. OPERATIONS

    View Slide

  65. OPERATIONS
    WHAT ARE THE ENTRY POINTS TO THE GRAPH?

    View Slide

  66. QUERY: PLEASE GIVE ME THIS DATA

    View Slide

  67. View Slide

  68. MUTATION: PLEASE CHANGE THIS DATA

    View Slide

  69. SUBSCRIPTION: PLEASE UPDATE ME IF DATA CHANGES

    View Slide

  70. View Slide


  71. HOW THINGS ARE RELATED

    View Slide


  72. HOW THINGS ARE RELATED

    WHAT YOU CAN ASK FOR

    View Slide


  73. HOW THINGS ARE RELATED

    WHAT YOU CAN ASK FOR

    HOW YOU ASK FOR IT

    View Slide

  74. GRAPHIQL

    View Slide

  75. View Slide

  76. View Slide

  77. View Slide

  78. View Slide

  79. View Slide

  80. View Slide

  81. View Slide

  82. View Slide

  83. View Slide

  84. View Slide

  85. View Slide

  86. View Slide

  87. View Slide

  88. View Slide

  89. View Slide

  90. View Slide

  91. View Slide

  92. View Slide

  93. HOW WOULD REST DO THIS?

    View Slide

  94. View Slide

  95. View Slide

  96. View Slide

  97. View Slide

  98. View Slide

  99. View Slide

  100. View Slide

  101. VALIDATION

    View Slide

  102. View Slide

  103. !

    View Slide

  104. VALIDATION
    IS WHAT I'M TRYING TO ASK FOR EVEN POSSIBLE?

    View Slide

  105. View Slide

  106. View Slide

  107. View Slide

  108. VALIDATION + TYPES =
    CODE GENERATION

    View Slide

  109. APOLLO IOS

    View Slide

  110. View Slide


  111. (IT ME)

    View Slide

  112. View Slide

  113. View Slide

  114. A VERY SHORTENED
    VERSION OF APOLLO'S GENERATED CODE

    View Slide

  115. public final class LaunchInfoQuery: GraphQLQuery {
    public init(id: GraphQLID) {
    self.id = id
    }
    public struct Data: GraphQLSelectionSet {
    public var launch: Launch? {
    public struct Launch: GraphQLSelectionSet {
    public var site: String?
    public var mission: Mission?
    public var rocket: Rocket?
    public struct Mission: GraphQLSelectionSet {
    public var name: String?
    }
    public struct Rocket: GraphQLSelectionSet {
    public var name: String?
    }
    }
    }
    }

    View Slide

  116. public final class LaunchInfoQuery: GraphQLQuery {
    public init(id: GraphQLID) {
    self.id = id
    }
    public struct Data: GraphQLSelectionSet {
    public var launch: Launch? {
    public struct Launch: GraphQLSelectionSet {
    public var site: String?
    public var mission: Mission?
    public var rocket: Rocket?
    public struct Mission: GraphQLSelectionSet {
    public var name: String?
    }
    public struct Rocket: GraphQLSelectionSet {
    public var name: String?
    }
    }
    }
    }

    View Slide

  117. public final class LaunchInfoQuery: GraphQLQuery {
    public init(id: GraphQLID) {
    self.id = id
    }
    public struct Data: GraphQLSelectionSet {
    public var launch: Launch? {
    public struct Launch: GraphQLSelectionSet {
    public var site: String?
    public var mission: Mission?
    public var rocket: Rocket?
    public struct Mission: GraphQLSelectionSet {
    public var name: String?
    }
    public struct Rocket: GraphQLSelectionSet {
    public var name: String?
    }
    }
    }
    }

    View Slide

  118. public final class LaunchInfoQuery: GraphQLQuery {
    public init(id: GraphQLID) {
    self.id = id
    }
    public struct Data: GraphQLSelectionSet {
    public var launch: Launch? {
    public struct Launch: GraphQLSelectionSet {
    public var site: String?
    public var mission: Mission?
    public var rocket: Rocket?
    public struct Mission: GraphQLSelectionSet {
    public var name: String?
    }
    public struct Rocket: GraphQLSelectionSet {
    public var name: String?
    }
    }
    }
    }

    View Slide

  119. View Slide

  120. public final class LaunchInfoQuery: GraphQLQuery {
    public init(id: GraphQLID) {
    self.id = id
    }
    public struct Data: GraphQLSelectionSet {
    public var launch: Launch? {
    public struct Launch: GraphQLSelectionSet {
    public var site: String?
    public var mission: Mission?
    public var rocket: Rocket?
    public struct Mission: GraphQLSelectionSet {
    public var name: String?
    }
    public struct Rocket: GraphQLSelectionSet {
    public var name: String?
    }
    }
    }
    }

    View Slide

  121. public final class LaunchInfoQuery: GraphQLQuery {
    public init(id: GraphQLID) {
    self.id = id
    }
    public struct Data: GraphQLSelectionSet {
    public var launch: Launch? {
    public struct Launch: GraphQLSelectionSet {
    public var site: String?
    public var mission: Mission?
    public var rocket: Rocket?
    public struct Mission: GraphQLSelectionSet {
    public var name: String?
    }
    public struct Rocket: GraphQLSelectionSet {
    public var name: String?
    }
    }
    }
    }

    View Slide

  122. YOU DON'T HAVE TO WRITE THIS CODE

    View Slide

  123. YOU DON'T HAVE TO WRITE THIS CODE
    (TIMES THE NUMBER OF OPERATIONS)

    View Slide

  124. YOU DON'T HAVE TO WRITE A
    URLSESSION WRAPPER

    View Slide

  125. View Slide

  126. YOU DO HAVE TO WRITE SOME CODE

    View Slide

  127. apolloClient.fetch(query: LaunchInfoQuery(id: "80")) { result in
    switch result {
    case .failure(let error):
    print("Error: \(error)")
    case .success(let graphQLResult):
    if let errors = graphQLResult.errors {
    print("Errors: \(errors)")
    }
    if let missionName = graphQLData?.data?.launch?.mission?.name {
    print("Mission name: \(String(describing: missionName)")
    }
    }
    }

    View Slide

  128. apolloClient.fetch(query: LaunchInfoQuery(id: "80")) { result in
    switch result {
    case .failure(let error):
    print("Error: \(error)")
    case .success(let graphQLResult):
    if let errors = graphQLResult.errors {
    print("Errors: \(errors)")
    }
    if let missionName = graphQLData?.data?.launch?.mission?.name {
    print("Mission name: \(String(describing: missionName)")
    }
    }
    }

    View Slide

  129. apolloClient.fetch(query: LaunchInfoQuery(id: "80")) { result in
    switch result {
    case .failure(let error):
    print("Error: \(error)")
    case .success(let graphQLResult):
    if let errors = graphQLResult.errors {
    print("Errors: \(errors)")
    }
    if let missionName = graphQLData?.data?.launch?.mission?.name {
    print("Mission name: \(String(describing: missionName)")
    }
    }
    }

    View Slide

  130. apolloClient.fetch(query: LaunchInfoQuery(id: "80")) { result in
    switch result {
    case .failure(let error):
    print("Error: \(error)")
    case .success(let graphQLResult):
    if let errors = graphQLResult.errors {
    print("Errors: \(errors)")
    }
    if let missionName = graphQLData?.data?.launch?.mission?.name {
    print("Mission name: \(missionName)
    }
    }
    }

    View Slide

  131. View Slide

  132. PARTIAL RESULTS

    View Slide

  133. apolloClient.fetch(query: LaunchInfoQuery(id: "80")) { result in
    switch result {
    case .failure(let error):
    print("Error: \(error)")
    case .success(let graphQLResult):
    if let errors = graphQLResult.errors {
    print("Errors: \(errors)")
    }
    if let missionName = graphQLData?.data?.launch?.mission?.name {
    print("Mission name: \(missionName)
    }
    }
    }

    View Slide

  134. apolloClient.fetch(query: LaunchInfoQuery(id: "80")) { result in
    switch result {
    case .failure(let error):
    print("Error: \(error)")
    case .success(let graphQLResult):
    if let errors = graphQLResult.errors {
    print("Errors: \(errors)")
    }
    if let missionName = graphQLData?.data?.launch?.mission?.name {
    print("Mission name: \(missionName)
    }
    }
    }

    View Slide

  135. USE SWIFT EXTENSIONS
    TO HANDLE NULLABILITY GRACEFULLY

    View Slide

  136. extension LaunchInfoQuery.Data.Launch {
    var missionName: String {
    self.mission?.name ?? "(Unknown)"
    }
    }

    View Slide

  137. View Slide

  138. WHAT IS GRAPHQL
    GOOD FOR?

    View Slide

  139. GET WHAT YOU WANT

    View Slide

  140. GET WHAT YOU WANT
    NOT WHAT FRONTEND, ANDROID, 3RD PARTY APIS, AND YOUR GRANDMA WANT

    View Slide

  141. YOU CAN ADD STUFF TO A GRAPH
    WAY FASTER THAN YOU CAN WITH A REST API

    View Slide

  142. A REST PLAY
    Me: Can we add this field that's on endpoint A to endpoint B?
    Backend: Sure, we'll put it in the backlog.

    View Slide

  143. View Slide

  144. ANYTHING IN THE SCHEMA
    CAN BE ACCESSED VIA THE
    RELATIONSHIPS DEFINED IN THE GRAPH

    View Slide

  145. user.father.bestFriend.children[0].middleName

    View Slide

  146. user.father?.bestFriend.children?[0].middleName

    View Slide

  147. WHAT IS GRAPHQL
    NOT GOOD FOR?

    View Slide

  148. UPLOADING FILES

    View Slide

  149. View Slide

  150. BETTER GRAPHQL UPLOADS

    View Slide

  151. BETTER GRAPHQL UPLOADS
    1. Upload to something that returns a URL

    View Slide

  152. BETTER GRAPHQL UPLOADS
    1. Upload to something that returns a URL
    2. Send the URL to your graph using GraphQL

    View Slide

  153. BETTER GRAPHQL UPLOADS
    1. Upload to something that returns a URL
    2. Send the URL to your graph using GraphQL
    3. Tear out way less hair than trying to upload with GQL

    View Slide

  154. HIGHLY OPTIMIZED QUERIES

    View Slide

  155. GQL TOOLING HELPS FIND BOTTLENECKS

    View Slide

  156. GQL TOOLING HELPS FIND BOTTLENECKS
    (BUT IT CAN'T ELIMINATE THEM)

    View Slide

  157. BEING ABLE TO
    !
    COMPLETELY REMOVE
    THINGS QUICKLY

    View Slide

  158. GOOD NEWS: NO VERSIONING

    View Slide

  159. BAD NEWS: NO VERSIONING

    View Slide

  160. @deprecated

    View Slide

  161. View Slide

  162. !

    "

    View Slide

  163. SIMPLE SECURITY

    View Slide

  164. YOU CAN ASK FOR ANYTHING YOU WANT!

    View Slide

  165. DEVELOPERS

    View Slide

  166. SECURITY TEAM

    View Slide

  167. View Slide

  168. View Slide

  169. YOU'RE GONNA HAVE TO THINK
    MORE GRANULARLY
    ABOUT SECURITY

    View Slide

  170. MAYBE DON'T LEAVE SCHEMA INTROSPECTION
    UNPROTECTED

    View Slide

  171. OBLIGATORY SUMMARY SLIDE

    View Slide

  172. OBLIGATORY SUMMARY SLIDE
    ▸ A Graph is a way of conceptualizing data based on pieces of data
    (nodes) and the ways those pieces are connected (edges).

    View Slide

  173. OBLIGATORY SUMMARY SLIDE
    ▸ A Graph is a way of conceptualizing data based on pieces of data
    (nodes) and the ways those pieces are connected (edges).
    ▸ GraphQL is a way of querying your data and how it's connected

    View Slide

  174. OBLIGATORY SUMMARY SLIDE
    ▸ A Graph is a way of conceptualizing data based on pieces of data
    (nodes) and the ways those pieces are connected (edges).
    ▸ GraphQL is a way of querying your data and how it's connected
    ▸ The Schema defines what you can ask for (with types!)

    View Slide

  175. OBLIGATORY SUMMARY SLIDE
    ▸ A Graph is a way of conceptualizing data based on pieces of data
    (nodes) and the ways those pieces are connected (edges).
    ▸ GraphQL is a way of querying your data and how it's connected
    ▸ The Schema defines what you can ask for (with types!)
    ▸ Operations let you ask for and receive only the data you want

    View Slide

  176. OBLIGATORY SUMMARY SLIDE
    ▸ A Graph is a way of conceptualizing data based on pieces of data
    (nodes) and the ways those pieces are connected (edges).
    ▸ GraphQL is a way of querying your data and how it's connected
    ▸ The Schema defines what you can ask for (with types!)
    ▸ Operations let you ask for and receive only the data you want
    ▸ GraphQL is a real cool hammer - not every problem is a nail

    View Slide

  177. WANT TO TRY APOLLO-IOS?
    https://www.apollographql.com/docs/ios/tutorial/
    THANK YOU!

    View Slide