Beyond REST API

Beyond REST API

C4db14b923561bc57fc10725abbecbcf?s=128

Lin Min Phyo

December 22, 2019
Tweet

Transcript

  1. Beyond REST API @Linminphyoe1 https://lin.phyo.work better.hr

  2. We all know REST API

  3. What we faced @ Better HR

  4. V1

  5. API Schema • V1 • GET https://www.better.hr/api/web/profile/{id} • GET https://www.better.hr/api/web/profiles

  6. V2

  7. V2 Changes • New tab for Activity Log is added

    • Create new API for Activity Log
  8. API Schema • V2 • GET https://www.better.hr/api/web/profile/{id} • GET https://www.better.hr/api/web/profiles

    • GET https://www.better.hr/api/web/activiylog/{id} • GET https://www.better.hr/api/web/activiylogs
  9. V3

  10. V3 Changes • Added Payroll tab • Move payroll related

    fields from profile to payroll tab • Clean up old API
  11. API Schema • V3 • GET https://www.better.hr/api/web/profile/{id} • GET https://www.better.hr/api/web/profiles

    • GET https://www.better.hr/api/web/activiylog/{id} • GET https://www.better.hr/api/web/activiylogs • GET https://www.better.hr/api/web/payroll/{id} • GET https://www.better.hr/api/web/payrolls
  12. None
  13. And .. Mobile Apps

  14. Things to consider for Mobile Apps • JSON should be

    as lightweight as possible • Backward compatible APIs
  15. Mobile endpoints • GET https://www.better.hr/api/mobile/profile/{id} • GET https://www.better.hr/api/mobile/profiles • GET

    https://www.better.hr/api/mobile/activiylog/{id} • GET https://www.better.hr/api/mobile/activiylogs • GET https://www.better.hr/api/mobile/payroll/{id} • GET https://www.better.hr/api/mobile/payrolls
  16. 12 APIs now. It is GET method only now

  17. 2 Web Devs 1 Frontend, 1 Backend, New releases every

    week
  18. Backend Dev

  19. Future We foresee other problems, too.

  20. Maintaining It’s not that easy

  21. Maintaining • API schema is growing fast • Single Source

    of Truth doesn’t exist
  22. Versioning Another problem after going production

  23. Versioning • https://www.better.hr/api/web/v1/….. • https://www.better.hr/api/web/v2/….. • https://www.better.hr/api/mobile/v1/….. • https://www.better.hr/api/mobile/v2/….. API

    endpoints doubled
  24. Upcoming features …

  25. Fingerprints Employee Schedules Contacts Notifications Attendances Leaves Team’s attendance Team’s

    leaves Login Files Assets Policies Permissions Profile
  26. What we realize • More frequent changes = More problems

    • More releases = More problems • More feature changes = More problems • More UI changes = More problems
  27. Explore a new thing. • Reduce loads of API developers

    • Want Single Source of Truth • Lightweight network calls • Easy to evolve over time • Want to experiment something new
  28. We found GraphQL

  29. How is it differ from REST ?

  30. GraphQL is Inversion of Control

  31. Backend Dev Frontend Dev Mobile Dev - Build API -

    Make changes Consumes API Consumes API REST
  32. Backend Dev Frontend Dev Mobile Dev Build Schema, which information

    is opened for clients Consumes API Consumes API GraphQL Ask required information Ask required information
  33. Ref : https://blog.apollographql.com/graphql-vs-rest-5d425123e34b

  34. None
  35. None
  36. GraphQL opens querying fields from Front-end developer, not defined by

    API developer.
  37. Magic?

  38. NO

  39. GraphQL is an extension built on top of REST API

  40. REST curl -X GET -H "Content-Type: application/json" https://www.example.com/users

  41. REST curl -X POST -H "Content-Type: application/json" --data '{ "query":

    "{ users { name } }" }' https://www.example.com/graphql curl -X GET -H "Content-Type: application/json" https://www.example.com/users GraphQL
  42. curl -X GET -H "Content-Type: application/json" https://www.example.com/users curl -X POST

    -H "Content-Type: application/json" --data '{ "query": "{ users { name } }" }' https://www.example.com/graphql REST GraphQL
  43. So, how do I know which information client can get?

  44. Server Side I can give you this User info :

    ID, Name, Nick Name, Job Title, Salary, Phone, Address, Gender
  45. type User { id : String name: String nickName: String

    jobTitle : String salary : Float phone : String address : String gender : Gender } I can give you this User info : ID, Name, Nick Name, Job Title, Salary, Phone, Address, Gender GraphQL Schema
  46. What is GraphQL Schema

  47. GraphQL Schema • Provided by Backend • Documentation that shows

    information provided for clients https://graphql.org/learn/schema/
  48. type User { id : String name: String nickName: String

    jobTitle : String salary : Float phone : String address : String gender : Gender } I can give you this User info : ID, Name, Nick Name, Job Title, Salary, Phone, Address, Gender GraphQL Schema
  49. Okay. Give me Name & Phone Client Side Client wants

    some information
  50. Query query { user { name phone } } Okay.

    Give me Name & Phone
  51. Result { "data": { “user": { "name": "Lin Phyo", "phone":

    “+959950001234" } } } query { user { name phone } } API returns
  52. Result { "data": { “user": { "name": "Lin Phyo", "phone":

    “+959950001234”, "email": “lin@better.hr”, } } } query { user { name phone email } } API returns Request Parameter
  53. Result { "data": { “user": { "id": “u0001”, "name": "Lin

    Phyo", "phone": “+959950001234”, "email": “lin@better.hr”, } } } query { user { id name phone email } } API returns Request Parameter
  54. GraphQL - A query language

  55. select * from user

  56. select * from user select name, phone from user

  57. query { users { name phone } } select name,

    phone from user
  58. query { users { name phone } } select name,

    phone from user
  59. query { users { name phone } } select name,

    phone from user
  60. query { users { name phone } } select name,

    phone from user
  61. query { users { name phone } } select name,

    phone from user where id = 1
  62. query { users( id = 1 ) { name phone

    } } select name, phone from user where id = 1
  63. query { users( id = 1 ) { name phone

    } } select name, phone from user where id = 1
  64. Mutation Equivalent to POST in REST

  65. You can update this User information : Nick Name, Phone

    & Address Server Side Client wants to update some information
  66. Okay. I want to update Nick name & Phone Client

    Side Client wants to update some information
  67. Mutation mutation { }

  68. Mutation mutation { updateMe(nickName:”Lin Phyo”, phone:”0987654321” ) { ... }

    }
  69. Mutation mutation { updateMe(nickName:”Lin Phyo”, phone:”0987654321” ) { updatedAt }

    }
  70. Mutation mutation { updateMe(nickName:”Lin Phyo”, phone:”0987654321” ) { updatedAt nickName

    Phone } }
  71. GraphQL Workflow

  72. https://lighthouse-php.com/tutorial/#what-is-lighthouse

  73. None
  74. None
  75. None
  76. None
  77. None
  78. None
  79. GraphQL Server GraphQL Client

  80. React import gql from 'graphql-tag'; import { useQuery } from

    '@apollo/react-hooks'; const GET_DOGS = gql` { dogs { id breed } } `; const { loading, error, data } = useQuery(GET_DOGS);
  81. React import gql from 'graphql-tag'; import { useQuery } from

    '@apollo/react-hooks'; const GET_DOGS = gql` { dogs { id breed } } `; const { loading, error, data } = useQuery(GET_DOGS);
  82. Android / iOS > apollo client:download-schema [OUTPUT] Download GraphQL Schema

    provided by backend
  83. Android / iOS > apollo client:download-schema [OUTPUT] Put it inside

    project
  84. Android / iOS > apollo client:download-schema [OUTPUT] Put it inside

    project query GetMyProfile { me{ id name email } } Write the query you want : GetMyProfile.graphql
  85. Android / iOS > apollo client:download-schema [OUTPUT] Put it inside

    project Write the query you want : GetMyProfile.graphql Build Project which will automatically run > apollo client:codegen [OUTPUT] API.swift for iOS or GetMyProfileQuery.java
  86. Android / iOS > apollo client:download-schema [OUTPUT] Put it inside

    project Write the query you want : GetMyProfile.graphql Build Project which will automatically run > apollo client:codegen [OUTPUT] Use generated method or class to call API
  87. More about GraphQL

  88. Named Queries

  89. Without Naming query { users( id = 1 ) {

    name phone } }
  90. Named Query query GetUser { users( id = 1 )

    { name phone } }
  91. Variables

  92. Without Variables query GetUser { users( id = 1 )

    { name phone } }
  93. With Variables query GetUser($id : Int) { users( id =

    $id ) { name phone } } { “id” : 1 }
  94. Aliasing Mapping fields as required

  95. Without Aliasing query GetUser($id : Int) { users( id =

    $id ) { name phone } } { “id” : 1 }
  96. With Aliasing query GetUser($id : Int) { employees : users(

    id = $id ) { name phone } } { “id” : 1 }
  97. Enums

  98. Enums enum EmployeeStatus { ACTIVE, DEACTIVE, DELETE }

  99. Enums enum EmployeeStatus { ACTIVE, DEACTIVE, DELETE } type User

    { name : String, status : EmployeeStatus }
  100. Enums query GetEmployeeStatuses { users { name status } }

    type User { name : String, status : EmployeeStatus }
  101. Enums query GetEmployeeStatuses { users { name status } }

    { "data": { "users": [ { "name": “John Doe", "status": "ACTIVE" }, ... ] } }
  102. Enums { "data": { "users": [ { "name": “John Doe",

    "status": "ACTIVE" }, ... ] } } enum EmployeeStatus { ACTIVE, DEACTIVE, DELETE }
  103. Interfaces

  104. Interfaces interface Notification{ id: ID! title: String! description: String! }

  105. Interfaces type NotiTypeA implements Notification { id: ID! title: String!

    description: String! } interface Notification{ id: ID! title: String! description: String! }
  106. Interfaces interface Notification{ id: ID! title: String! description: String! }

    type NotiTypeB implements Notification { id: ID! title: String! description: String! attachmentsUrls: [String!]! } type NotiTypeA implements Notification { id: ID! title: String! description: String! }
  107. Unions

  108. Unions union User = DashboardUser | MobileUser | NonMobileUser

  109. Unions union User = DashboardUser | MobileUser | NonMobileUser {

    users { ... on DashboardUser { role } ... on MobileUser { deviceID } ... on NonMobileUser { officeID } } }
  110. Unions union User = DashboardUser | MobileUser | NonMobileUser {

    users { ... on DashboardUser { role } ... on MobileUser { deviceID } ... on NonMobileUser { officeID } } }
  111. Unions union User = DashboardUser | MobileUser | NonMobileUser {

    users { ... on DashboardUser { role } ... on MobileUser { deviceID } ... on NonMobileUser { officeID } } }
  112. Unions union User = DashboardUser | MobileUser | NonMobileUser {

    users { ... on DashboardUser { role } ... on MobileUser { deviceID } ... on NonMobileUser { officeID } } }
  113. Fragments Grouping same structure for code reuse

  114. Fragments fragment NameAndProfile on User{ name: String! profileUrl: String! }

  115. Fragments fragment NameAndProfile on User{ name: String! profileUrl: String! }

    query { users { ... NameAndProfile } }
  116. Subscriptions Real-time GraphQL queries

  117. Error Handling

  118. Error format { "data": { ... }, "errors": [ ...

    ] }
  119. Resources GraphQL Official Website https://graphql.org/ Explore GraphQL https://graphql.com/

  120. Tooling Altair GraphQL Client https://altair.sirmuel.design/ IntelliJ Plugin https://github.com/jimkyndemeyer/js-graphql-intellij-plugin Apollo Platform

    https://www.apollographql.com/docs/intro/platform Apollo CLI https://github.com/apollographql/apollo-tooling
  121. Apollo Platform • Apollo Server • Apollo Client • iOS

    and Android • Apollo CLI https://www.apollographql.com/docs/intro/platform#open- source
  122. Final Thoughts

  123. Is that perfect?

  124. No

  125. Drawbacks • Multipart request is not out of the box

    • Server side caching is harder compared to REST • Rate limiting for public APIs • Careless developers problem • Project handover
  126. But, we gain • Write once, query anywhere • Single

    source of truth • Faster frontend, mobile development • Able to call different data nodes in one API call • Easier to analyze which fields are requested by whom • Easier to grow overtime • Performant API
  127. Drawbacks faced by Mobile Developers • Generated model is not

    ready to use • Tons of null checks
  128. Which companies are using GraphQL ??

  129. … better.hr

  130. Should I use GraphQL in our project ??

  131. It depends.

  132. • Long term project • Products • Different clients using

    the same backend • Open-source APIs
  133. Playground https://api.spacex.land/graphql

  134. Write queries, not codes @Linminphyoe1 https://lin.phyo.work https://speakerdeck.com/hashlin Get the slides

    @
  135. @Linminphyoe1 https://lin.phyo.work Take a ride through a Burmese tech scene

    made by Burmese, for Burmese https://anchor.fm/techshaw @vincentpaing