GraphQL: An API Convention That You Will Actually Follow

Clement Hannicq speaking at London Node User Group in January, 2017
186Views
 
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

REST is recognised as the "good practice" in terms of web APIs, but can quickly become a hassle as your application grows and evolves. GraphQL is a new paradigm, allowing developers to request deeply nested information in a single call, without cluttering the response with unneeded fields. In this talk, Clement Hannicq will show you how GraphQL overcomes the REST limitations to send only the information a caller wants, without changing anything in the backend.


Transcript


So, today I will be talking to you about GraphQL. So, first I'd like to share a story with you. So, it did not exactly happen, I'm quite changing a lot of details as to avoid any NSA complication, but the main idea is there. So basically, I was working on this project, and it was a pretty classic project. A fountain, we were using React, on the back end we had an API. And everything was working fine, the goal of the project was, and I'm completely lying there. It's not this at all, but let's imagine it was, displaying quotes from characters from movies on a page. Okay, so I had a REST API with three entities, characters, quotes, and movies. I don't know, on some page, it listed quotes with the name of the character and in parentheses, the movie. So, I had this RESTful API and everyone was happy until it came out in the front end of the I was working on the new version, and for me it's easy to use, but it will be easier when I create a list of quotes, instead of giving a new URL to the character that said this quote, "I'm getting his name," because I don't like to have to make like 10,000 calls for the single page just to research everything. And I was like, "Okay, but if I start doing this, I'm going to break the RESTful contract. Does this story echoes with everyone? Anyone in that? Yeah, I have one yes. - [Man] Yes. - Two. Perfect. I was trying to reach at least one person with that story. So, that's when I said, okay, it will be very easier if I had his name. Okay, but this doesn't make sense. I'm going to break the API on every new we say, It's not a RESTful API, because for an API we didn't have full documentation on this because it's non-standard. So, okay, just on one field, I will do it. One week after, same developer, I'm not kidding, "I'd kind of like also to get the name of the movie." I add the name of the movie into my funnel, and "Thank you, man, can I possibly get the date of the movie, when the movie was published, and also the frame, the image of the character's scene that the quote, and a lot of other stuff." And I was like, "Okay, this is not a RESTful API just want me to give you a full JSON of all the data we have, and be done with it." So, I did not do this, because it's a very bad thing to do, but it was a possibility for me to say, "Okay, this is an endpoint, you post, an SQL request, and you will get everything you want, and you will stop bothering me." Don't do this, no, don't, it's not a good idea. Then, GraphQL happened. So, what is GraphQL? Does everyone here knows what it is? Can you...? About a third of the room, very good. So the idea of GraphQL, is it's another convention, it's like REST, except it's better. Otherwise I wouldn't be speaking about it. And I think, instead of giving long explanations, on how it works, and what those are, I think it would be better to show you. So, nope, nope, yeah. So, here I have like an interface to my API so, it's kind of like a with GraphQL APIs. And for those who are interested, the underlying implementation of GraphQL because as I said, GraphQL is a convention not a framework. I'm using Express GraphQL, because there's no documentation on it. I'm kidding. There's really no documentation on it, but that's not the reason why I'm using it. So, the idea is, your front end developer will send a payload which is basically the shape of the data he's asking for. So, I could ask for quotes... So, here I made this shape, I can prettify it, So, the idea is, I asked for the quotes and I'm getting one of the quotes I asked for. Then I can ask for something else, so as I said, I had this front end developer who wanted to add the name of the character who said that quote. So, let's add this and with his name. And there I have for every quote the name of the character that said it. He also wanted to have the movie. Also by name. Where this quote appeared. And then he wanted a lot of other stuff you can imagine, let's say the list of characters in the movie. So, the name, and here I have a very complicated search of basically every information I ask for I'm getting and I only want to get the information I need. And this is going to be an important point going on. That pretty much works, to be noted also comes with automatically generated documentation. So, for example, I can see that when I ask about quotes, I get an array of quotes, and that the quote has a movie, a person, and the quote itself. Now, there's another functionality that might be useful is, when you work on an API, the API is a contract you are facing between the front-end developer and the back-end developer. If you are an on-site developer, be that much interesting, it becomes very important when you're working on a team. Basically, you want people to, when they call your API, you want them to know what they're getting. If I'm asking for a field and I don't know if I'm getting updates on the data or anything, it's of little use to me. Can you still hear me? Thank you. So, I was saying, yes, contract. On a REST API, the contract is pretty much the documentation itself. You have to add documentation that said what you are getting. That's about it. On GraphQL, everything is typed strongly, so you can already see that this on the documentation basically, every field has a very specific type which can either be I type defined myself or base type. And you also have information of on which fields are required, and which fields are not. Another side effect, if I ask about person, for example, there's also the contract on the other way. There's also a contract on which parameters I, as a back-end developer, I am expecting the user to give me. So, for example, if I call person, the contract is, they won't let me mess with it, to have an ID, which has to be a screen. And if I give him anything else, than a screen, or if I just forget to give him an ID, I will get a pretty explicit error, so here, the API was expecting a string and it got an ID. Furthermore, all the information I have about the types and the schema, is accessible, through in store station. So, I can write a query to my API to know exactly what I'm getting and I can do this permanently because this API is standardised. So, if I have a GraphQL API, I know, and I know it in GraphQL I know exactly what this API will be giving me, and what do I need to give it to get the information I need. For example, let's get the list of types, name, and here on the list of types that are supported by the API, so some of them are supported by the API, so some of them are custom defined. I defined the quotes, movie and person myself. The others are built-in in GraphQL. To be noted here, on my example, I have only get the methods, the updates create or delete, and the will work basically the same way, it will be a different type. And when GraphQL receives this type, it will know that it has to do. I wasn't showing it, but the base type of my request is a query. A query never have side-effects, the other side-effect like the other type that can be defined is a mutation. Mutation have side-effects but do not return data. Going back to, nope, presentation so, how does it look like in terms of code? So, the first thing, I said as a back-end developer I need to do is to define the type that will be exposed by the API. So, to define a type, it's relatively easy. I only need a name, and a list of fields and I'm giving, for everything, a description, that's to be able to have a self-document and write a recommendation that actually gives a bit of context to the end user. Most of the types will work by mapping to the object to be an underlying property, of the same name on the object. If I need something a bit more complicated, I can have resolve functions which I will be speaking more about later. Once I have all my types, I need to define a schema. So, a schema is, basically, how am I getting the information? The types define what is in the available information and the schema is how do I query it? So, think of it, schema can be seen as the type of the root of my query. So, here on my API, I define the person's endpoint which I was using to create persons. And to get a list of persons. Again, I have a result because things are not straightforward to get persons. A little bit on the resolve function itself, it's basically GraphQL works by having a resolve function that returns every object you need, which makes you, the back-end developer, able to make the choices you want. If the function returns a promise, it's also finding, GraphQL will find its way around it. So, the idea is, your data can come from a Mongo database, an SQL database, a file you're reading from the file system. Can even be an object that you're keeping in memory in your node process. It can be pretty much anything you want. It can even be an underlying REST API on another server that you are querying and getting the objects from. The only idea is, when I call this getPersons function, I must get the array of persons. If I'm inside a relationship, for example, here, I am disframing a movie and on persons the getPerson function will get, as a first parameter the instance of movie I want to get the persons from. So, if I want to do SQL joins, that's where I will do them. To sum it up, what GraphQL has over REST APIs, are that it's typed, it's self-documentation, and self-documentation as a standard. It supports introspection, which can be used from developer to know exactly what I'm getting, can even be used to write tests. I'm pretty sure you want to test that the API you are using because it's supported by another developer, you don't have control on the changes that can happen on it. The detail you are expecting to get. And it's a query language by itself, which means that the front-end developer will stop bothering you to add some data to the calls. Another thing you get from using GraphQL is deprecation. And I should use quotes are unavailable because it's a more different convention that is made easier by GraphQL instead of a very powerful feature, the language. The idea, in REST APIs is when you have a new version when you make changes, you just add a version number in the UL, that's it. The users that are still calling for the version 1, we still call the version 1 and get the data that they want. The users that want to use the new version, we'll call the version 2, and we'll get the new schema. That's pretty useful for developers, except for front-end developers, for back-end developers that means that you have more versions of your code to maintain. You have more versions of documentation to maintain, if you are to do, I don't know, a fix, you have to do it on every version, and make sure that you don't break anything on every version. Whereas, in GraphQL, the idea is, instead of having versions of your APIs, you only have one API, one endpoint, that will work on anything you want, and if you want to add something, you just add it. If you add a field, it won't change anything on the front-end side, because if the developer wasn't asking for this field before, well, he won't get it after you add this field. So, for on the front-end, I'm still getting exactly the same data as before, so no change for me. If I decide to have a field deprecated, I might deprecate it like I will do in API and a RESTful API, the main difference is, when you make a call to a REST endpoint, when you receive a call to one of your REST endpoints, actually, you have no idea what the user is interested in. You know you're returning, I don't know, like, five deprecated fields, but you don't know if your user is using them or if he's just getting them because he has no choice, basically. With GraphQL, since you are receiving as a payload the fields that the user want to get, you can do analytics on it. That means that when you start deprecating a field, you can keep track of how many people are still needing that field. And that means that when you are finally removing that field from the API, you know exactly how much person it will impact. You know who it will impact if your API has some kind of authentication mechanism written. And that's pretty much it, it's as easy as adding a deprecation reason on a field and it will, also, of course, show up in the automatic documentation. There are some points which have object where GraphQL would be performing not as well as REST. The first one would be caching. Caching requests in REST is pretty much straightforward, if it's a get request, and I have already in my cache I get a request with the same UL, when it's the same data, if my cache is not too old and I just push the data I have in cache and I'm done with it. If it's something else, that means that the user wants to add a side-effect and I shouldn't cache it. With GraphQL, everything is pretty much sent over post because you need to be able to send a payload. Well, the consumer needs to send a payload. So you have to dig a bit deeper to know if you can cache it or not. And also, since the user can ask for any shape of data he wants, well, it's not as effective, because there are an infinite number of ways to get the list of persons in a GraphQL API, whereas in REST, if you have, like three endpoints to get different persons depending on the filters when there's only three different kind of calls to cache. This is kind of mitigated by the fact that mostly the end users won't be making the GraphQL calls themselves, they will be using your application that is making the calls, and if the application is used by a certain amount of users then a lot of the requests that will be coming in, will actually be the same. Because it's only one application making requests, a lot of users on this application it's only one kind of request. So, that's something to be balanced, I think. The second point will be performance. As I said, your REST your API can be wired into a lot of things and it's not I'm receiving a call do I select on my database, from other data, and I send it back, it's more like, I get a request, what do the user wants, do I make a select for the first entity. Then I see that my user wants to take something else, and I made a seven select, to get the other information, I'm getting the information but I'm not still quite done yet because I need more information and just keep looping until I have all the information I want. So, a single call will of course, have a heavier hit on your performance. Then again, so does having 10,000 calls to your API just to get the list of quotes and the name of every person that put every quote. Lastly, the point I'm listing in cons is documentation. At least when I started playing with it, and I still haven't found it yet, I haven't found any documentation on the express implementation of GraphQL. So, most of the thing I managed to do with it was by looking at their code. It's open source, so thank god. But really, there was no other documentation on everything that I managed to make work was looking at their code and figuring out what was the name of the key I'm supposed to use.What am I supposed to use to send to GraphQL? It's very annoying and that will be the main reason I will not be using GraphQL yet on a production sales project, because I don't want to be the only one developer that actually knows how to use that technology. And, if you have any questions, yes. - [Man 2] So, I guess, so it kind of that last bit, but to a certain degree that answered it. But, when would you choose, like if you were given the option, and like kind of it was your own kind of personal project, would you choose REST like a straightforward REST API versus going the GraphQL route? It's just the complexity of the model in there...? - I'd go for yeah, many, well if GraphQL was a possibility, maybe if there's a team where everyone knows how to use it, then I guess, the deciding factor will be how complicated my model is. If I have like, two entities, and I'm only interested in the list of one, or the list of the other, eventually filtered, then of course, REST will be a lot easier. If I have a very relational data, and I need to get a lot of data always, and performance is a key, because one of the advantage I did not list is since I am only getting the data I want, the volume of the payload I'm receiving also can be a lot smaller than what I will get from an API. When make, for example, a call to the REST API of will to get, I don't know, the address of a restaurant, and I'm getting all kinds of data on this restaurant, who went, who visited this restaurant, how many stars stars does it have, the exact position, the tags, everything, I'm getting a ton of data that I don't care about, and when there's only one field and, of course, when you are developing applications on mobile, the bandwidth, and you are saving the field, it's an advantage. It's like, I would wait the complexity of the model and the needs for reduced bandwidth or faster development because the main advantage of GraphQL is you make the API and then you potentially don't have to do anything else with it. You can add features, but mainly on the back end any application you want on your data, and you be able to get it easily. I don't know if that answered your... - That was perfect. - Thank you. - [Woman] I think any more questions are going to have to be in the pub, but thank you, very much for coming.