Pro Yearly is on sale from $80 to $50! »

GraphQL From The Ground Up - Swift Heroes, Online, October 2020

GraphQL From The Ground Up - Swift Heroes, Online, October 2020

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

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.

C4861b1dfdf3bbb21faec4a1acdf183d?s=128

Ellen Shapiro
PRO

October 01, 2020
Tweet

Transcript

  1. GRAPHQL FROM THE GROUND UP SWIFT HEROES | THE INTERNETS

    | OCTOBER 2020 ELLEN SHAPIRO | @DESIGNATEDNERD | APOLLOGRAPHQL.COM
  2. None
  3. None
  4. None
  5. WTF IS GRAPHQL?

  6. None
  7. WHAT IS A GRAPH?

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

  10. ! GRAPH THEORY

  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
  12. None
  13. Source: https://neo4j.com/blog/graph-theory-predictive-modeling/

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

  15. None
  16. UNDIRECTED GRAPH

  17. NODES INDIVIDUAL PIECES OF DATA

  18. EDGES RELATIONSHIPS BETWEEN PIECES OF DATA

  19. None
  20. SO IS A RELATIONAL DATABASE A GRAPH? !

  21. NOT QUITE.

  22. None
  23. None
  24. None
  25. None
  26. RELATIONAL DATABASES ARE FOCUSED ON SINGLE RELATIONSHIPS

  27. GRAPHS HELP YOU TO TRACK MANY RELATIONSHIPS

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

  29. ✨ GRAPHQL!

  30. GRAPH QUERY LANGUAGE

  31. HOW DO I GRAPHQL?

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

  33. THE SCHEMA

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

  35. SCHEMA DEFINITION LANGUAGE

  36. SCHEMA DEFINITION LANGUAGE (BASICALLY, TYPESCRIPT)

  37. None
  38. None
  39. None
  40. None
  41. SCALAR TYPES

  42. SCALAR TYPES THE BUILDING BLOCKS OF THE TYPE SYSTEM

  43. OPTIONALS?!

  44. ✍ POP QUIZ!

  45. Q. IS THIS TYPE OPTIONAL?

  46. Q. IS THIS TYPE OPTIONAL? String

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

  48. None
  49. None
  50. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE

  51. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE No

  52. IS OPTIONAL SWIFT TYPE GRAPHQL TYPE No String

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

  54. !

  55. GRAPHQL TYPES ARE NULLABLE BY DEFAULT

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

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

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

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

    String? String
  60. None
  61. OPERATIONS

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

  63. QUERY: PLEASE GIVE ME THIS DATA

  64. None
  65. MUTATION: PLEASE CHANGE THIS DATA

  66. SUBSCRIPTION: PLEASE UPDATE ME IF DATA CHANGES

  67. None
  68. ✅ HOW THINGS ARE RELATED

  69. ✅ HOW THINGS ARE RELATED ✅ WHAT YOU CAN ASK

    FOR
  70. ✅ HOW THINGS ARE RELATED ✅ WHAT YOU CAN ASK

    FOR ➡ HOW YOU ASK FOR IT
  71. GRAPHIQL

  72. None
  73. None
  74. None
  75. None
  76. None
  77. None
  78. None
  79. None
  80. None
  81. None
  82. None
  83. None
  84. None
  85. None
  86. None
  87. None
  88. None
  89. HOW WOULD REST DO THIS?

  90. None
  91. None
  92. None
  93. None
  94. None
  95. None
  96. None
  97. VALIDATION

  98. None
  99. !

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

  101. None
  102. None
  103. None
  104. VALIDATION + TYPES = CODE GENERATION

  105. APOLLO IOS

  106. None
  107. ⬆ (IT ME)

  108. None
  109. None
  110. A VERY SHORTENED VERSION OF APOLLO'S GENERATED CODE

  111. 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? } } } }
  112. 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? } } } }
  113. 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? } } } }
  114. 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? } } } }
  115. None
  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? } } } }
  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? } } } }
  118. YOU DON'T HAVE TO WRITE THIS CODE

  119. YOU DON'T HAVE TO WRITE THIS CODE (TIMES THE NUMBER

    OF OPERATIONS)
  120. YOU DON'T HAVE TO WRITE A URLSESSION WRAPPER

  121. None
  122. YOU DO HAVE TO WRITE SOME CODE

  123. 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)") } } }
  124. 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)") } } }
  125. 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)") } } }
  126. 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) } } }
  127. None
  128. PARTIAL RESULTS

  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: \(missionName) } } }
  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) } } }
  131. USE SWIFT EXTENSIONS TO HANDLE NULLABILITY GRACEFULLY

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

    } }
  133. None
  134. WHAT IS GRAPHQL GOOD FOR?

  135. GET WHAT YOU WANT

  136. GET WHAT YOU WANT NOT WHAT FRONTEND, ANDROID, 3RD PARTY

    APIS, AND YOUR GRANDMA WANT
  137. YOU CAN ADD STUFF TO A GRAPH WAY FASTER THAN

    A REST API*
  138. 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.
  139. None
  140. ANYTHING IN THE SCHEMA CAN BE ACCESSED VIA RELATIONSHIPS IN

    THE GRAPH
  141. user.father.bestFriend.children[0].middleName

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

  143. WHAT IS GRAPHQL NOT GOOD FOR?

  144. UPLOADING FILES

  145. None
  146. BETTER GRAPHQL UPLOADS

  147. BETTER GRAPHQL UPLOADS 1. Upload to something that returns a

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

    URL 2. Send the URL to your graph using GraphQL
  149. 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
  150. HIGHLY OPTIMIZED QUERIES

  151. GQL TOOLING HELPS FIND BOTTLENECKS

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

  153. BEING ABLE TO ! COMPLETELY REMOVE THINGS QUICKLY

  154. GOOD NEWS: NO VERSIONING

  155. BAD NEWS: NO VERSIONING

  156. @deprecated

  157. None
  158. ! → " →

  159. SIMPLE SECURITY

  160. YOU CAN ASK FOR ANYTHING YOU WANT!

  161. DEVELOPERS

  162. SECURITY TEAM

  163. None
  164. None
  165. YOU'RE GONNA HAVE TO THINK MORE GRANULARLY ABOUT SECURITY

  166. MAYBE DON'T LEAVE SCHEMA INTROSPECTION UNPROTECTED

  167. OBLIGATORY SUMMARY SLIDE

  168. 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).
  169. 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
  170. 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!)
  171. 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
  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). ▸ 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
  173. WANT TO TRY APOLLO-IOS? https://www.apollographql.com/docs/ios/tutorial/ THANK YOU!