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

GraphQL From The Ground Up - Apollo Mobile Day, Online, January 2021

GraphQL From The Ground Up - Apollo Mobile Day, Online, January 2021

Video: Coming soon!

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 mobile development process? Ellen Shapiro, who maintains the Apollo GraphQL iOS SDK, will help untangle all this and more.

Ellen Shapiro

January 26, 2021
Tweet

More Decks by Ellen Shapiro

Other Decks in Technology

Transcript

  1. GRAPHQL FROM THE GROUND UP
    APOLLO MOBILE DAY | THE INTERNETS | JANUARY 2021
    ELLEN SHAPIRO | @DESIGNATEDNERD | APOLLOGRAPHQL.COM

    View full-size slide

  2. WTF IS GRAPHQL?

    View full-size slide

  3. WHAT IS A GRAPH?

    View full-size slide

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

    View full-size slide

  5. !
    GRAPH THEORY

    View full-size slide

  6. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  12. UNDIRECTED GRAPH

    View full-size slide

  13. NODES
    INDIVIDUAL PIECES OF DATA

    View full-size slide

  14. EDGES
    RELATIONSHIPS BETWEEN PIECES OF DATA

    View full-size slide

  15. SO IS A RELATIONAL DATABASE A GRAPH?
    !

    View full-size slide

  16. RELATIONAL DATABASES ARE FOCUSED ON
    SINGLE RELATIONSHIPS

    View full-size slide

  17. GRAPHS HELP YOU TO TRACK
    MANY RELATIONSHIPS

    View full-size slide

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

    View full-size slide

  19. GRAPH QUERY LANGUAGE

    View full-size slide

  20. HOW DO I GRAPHQL?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  23. SCHEMA DEFINITION LANGUAGE

    View full-size slide

  24. SCHEMA DEFINITION LANGUAGE
    (BASICALLY, TYPESCRIPT)

    View full-size slide

  25. SCALAR TYPES

    View full-size slide

  26. SCALAR TYPES
    THE BUILDING BLOCKS OF THE TYPE SYSTEM

    View full-size slide


  27. POP QUIZ!

    View full-size slide

  28. Q. IS THIS TYPE OPTIONAL?

    View full-size slide

  29. Q. IS THIS TYPE OPTIONAL?
    String

    View full-size slide

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

    View full-size slide

  31. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE

    View full-size slide

  32. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No

    View full-size slide

  33. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No String

    View full-size slide

  34. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No String String!

    View full-size slide

  35. GRAPHQL TYPES ARE
    NULLABLE BY DEFAULT

    View full-size slide

  36. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No String String!

    View full-size slide

  37. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No String String!
    Yes

    View full-size slide

  38. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No String String!
    Yes String?

    View full-size slide

  39. IS OPTIONAL SWIFT/KOTLIN TYPE GRAPHQL TYPE
    No String String!
    Yes String? String

    View full-size slide

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

    View full-size slide

  41. QUERY: PLEASE GIVE ME THIS DATA

    View full-size slide

  42. MUTATION: PLEASE CHANGE THIS DATA

    View full-size slide

  43. SUBSCRIPTION: PLEASE UPDATE ME IF DATA CHANGES

    View full-size slide


  44. HOW THINGS ARE RELATED

    View full-size slide


  45. HOW THINGS ARE RELATED

    WHAT YOU CAN ASK FOR

    View full-size slide


  46. HOW THINGS ARE RELATED

    WHAT YOU CAN ASK FOR

    HOW YOU ASK FOR IT

    View full-size slide

  47. HOW WOULD REST DO THIS?

    View full-size slide

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

    View full-size slide

  49. VALIDATION + TYPES =
    CODE GENERATION

    View full-size slide

  50. APOLLO IOS
    +
    APOLLO ANDROID

    View full-size slide

  51. A VERY SHORTENED
    VERSION OF APOLLO'S GENERATED IOS CODE

    View full-size slide

  52. 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 full-size slide

  53. 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 full-size slide

  54. 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 full-size slide

  55. 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 full-size slide

  56. 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 full-size slide

  57. 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 full-size slide

  58. YOU DON'T HAVE TO WRITE THIS CODE

    View full-size slide

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

    View full-size slide

  60. YOU DON'T HAVE TO WRITE A
    NETWORKING WRAPPER

    View full-size slide

  61. YOU DO HAVE TO WRITE SOME CODE

    View full-size slide

  62. 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 full-size slide

  63. 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 full-size slide

  64. 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 full-size slide

  65. 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 full-size slide

  66. PARTIAL RESULTS

    View full-size slide

  67. 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 full-size slide

  68. 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 full-size slide

  69. USE SWIFT + KOTLIN EXTENSIONS
    TO HANDLE NULLABILITY GRACEFULLY

    View full-size slide

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

    View full-size slide

  71. WHAT IS GRAPHQL
    GOOD FOR?

    View full-size slide

  72. GET WHAT YOU WANT

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  75. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  79. WHAT IS GRAPHQL
    NOT GOOD FOR?

    View full-size slide

  80. UPLOADING FILES

    View full-size slide

  81. BETTER GRAPHQL UPLOADS

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  84. 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 full-size slide

  85. HIGHLY OPTIMIZED QUERIES

    View full-size slide

  86. GQL TOOLING HELPS FIND BOTTLENECKS

    View full-size slide

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

    View full-size slide

  88. BEING ABLE TO
    !
    COMPLETELY REMOVE
    THINGS QUICKLY

    View full-size slide

  89. GOOD NEWS: NO VERSIONING

    View full-size slide

  90. BAD NEWS: NO VERSIONING

    View full-size slide

  91. SIMPLE SECURITY

    View full-size slide

  92. YOU CAN ASK FOR ANYTHING YOU WANT!

    View full-size slide

  93. SECURITY TEAM

    View full-size slide

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

    View full-size slide

  95. MAYBE DON'T LEAVE SCHEMA INTROSPECTION
    UNPROTECTED

    View full-size slide

  96. OBLIGATORY SUMMARY SLIDE

    View full-size slide

  97. 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 full-size slide

  98. 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 full-size slide

  99. 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 full-size slide

  100. 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 full-size slide

  101. 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 full-size slide

  102. WANT TO TRY APOLLO?
    https://www.apollographql.com/docs/ios/tutorial/
    https://www.apollographql.com/docs/android/tutorial/
    THANK YOU!

    View full-size slide