scala.bythebay.io: Dustin Whitney, GraphQL: IoC makes its way to HTTP ... and it's great!
Recording: scala.bythebay.io: Dustin Whitney, GraphQL: IoC makes its way to HTTP ... and it's great!
that's that's meant to it's a spec for querying an API so let's just dive in and by the way I felt this talk was ten minutes longer than I've got so we might hurry and this is not the beginning okay so this is me i'm dustin whitney i organized the new york scala meetup if you ever want to do a talk in new york let me know i'm also one of the organizers of the new york scala symposium i used to be the CTO of police analytics now i'm a project september I worked with some awesome people we have an open source library called freak it's a library for working with it takes a lot of the boilerplate out of working with free monads guy named Pascal vato or men do being put it together another guy named Gaetano Renato put together some libraries college he'll react geo react native and he worked with another person who I work with named mr. speaker you should check these libraries out there they're really awesome it enables WebGL through react so we're here to talk about graph QL and I just wanted to set I know the way I like to at least cure talks or give them is set up a problem and then try and understand how to solve it so I I've been doing a lot of work in startups pretty much since like 2007 or something like that so I'm gonna give this this talk from that that context and not everybody works at a start-up so you know it won't be a hundred percent germane to your situation but hopefully you can learn something from it and it's not only don't wanna stand up here and say this is the only way to do it because there's a bunch of ways for my perspective people are the the hardest thing and any startup easily and like let's set aside personality issues and just focus on actually just hiring some people you're about to set off on this adventure you may or may not have a lot of money and now I've got to go find a bunch of people who are ready to drop everything and go take this journey with you and of course you're gonna be working with a CEO who wants everything they want a website they want an iOS app they want an Android app and now of course they want an electron app so you're gonna need some way to and then on top of that you're gonna have these four different things they all need to be put out into a production server and you need to feel pretty good about it so that that's a lot it's a lot to take on and and when I think about that when I'm gonna go find these people to work on this team your iOS guy probably only knows iOS your Android guy probably only really knows Android your web guy might not know iOS or Android it's it's a tough problem to solve I gotta go find these three people just to work on this one small project and then I've got the DevOps problem in the back-end problem in addition to that if you're like me you're probably better at that and feel a little bit more confident about it so there's these other aspects that are they're a little bit tougher so I think some good solves are coming out of Facebook right now Facebook's doing some amazing stuff I think react react native and real a really address the issue of solving those first three people that you have to hire if you can find a really really solid react native guy he could build your iOS and Android app and your web app and probably I mean it depends on how it depends on how flexible the non tech part of your team is but maguet like 90 percent shared code between all these different platforms and they'll feel very native your entire interface can basically be built and then you've got a you know if you're gonna do payments you're gonna have to do your your Apple pay separately and your Google Wallet separately but you're gonna I mean you're probably gonna be able to find somebody who solid enough engineer that they can figure out to make that work on iOS and figure out how to make that work on Android so these are some great solutions to solve that that end of things the other side is the DevOps and back end and definitely some solutions that I like to solve this people problem where am I gonna get all these people and I can't really afford very money I guess I'm gonna start with AWS lambda haven't actually used it but I find it very attractive in the sense that on the server I can just kind of let it run and I think graph QL which we'll definitely get into it fits very nicely into AWS lambda because if I'm gonna launch a web serving thing on AWS lambda and I'm using rest then every single endpoint that I create I'm going to have to manage through what they call it an API gateway it's cuz it's just gonna be kind of painful and again you're a startup you're trying to work as fast as you possibly can I don't want to deal with this weird setup what you'll find with graph QL is there's really only two endpoints you're gonna van endpoint to serve up your schema we'll get to that an endpoint to take queries and then you're kind of done so just putting this thing out there is it's pretty simple in fact just anecdotally at project September I think we've changed out our web back-end three different times we've had play with that Finch and now we're on HTTP for us one day just to switch from each one it really easy I think we have six endpoints something like that so I talked about the inversion of control so I I mean probably if you're like me and you've been around a while the first thing that comes to your mind is spring because everyone just thinks of dependency injection it's probably the opposite of that now what I basically mean is just taking the way things are and inverting it so the way things are this this picture is meant to represent the way things are we've got a mobile device and a desktop device and then the URLs are meant to represent an API and then the lightning bolt says this API serves these two devices and I've segmented the API up into what I would call two different problems so the top API just shows me fetching everything from one single endpoint and that might work well in the beginning of your you know tiny little startup and you don't have much data and the app doesn't do a lot it's easy so I can just make this one query and I get everything for our user hero turski that's eventually gonna fall apart so you then break up the endpoints into many endpoints that fetch various different things and that might work well on your desktop that has a very steady connection with a lot of bandwidth but your mobile device might fall apart on that especially if you're making a lot of requests so you'll get that weird state where maybe not even all your requests are failing but some of them are just slow so your pages can render kind of poorly or just not at all and this is I don't know just a tough issue that that your front-end developer is going to have to come to it and you you what you're going to end up doing is basically building kind of two backends one that serves your your mobile app to accommodate for its needs and another that serves for your desktop at that accommodates its needs so graph QL solves this problem by essentially letting you query your API and fetch only the data that you need so if I if I have a mobile device and it has some performance requirements that you know need to work with a shady connection I can only I can ask for just the data that I need to render a screen that will look good in that type of environment and you know conversely with the desktop I can get everything I want all at once and the back end doesn't have to change anything they just need to expose a schema and an endpoint to take in a query and then your front-end in your back-end and your mobile developer and your desktop developer hopefully the same person can experiment with different queries to see what is more appropriate for the the product of their building anyway so let's get more into what is graph QL so I've talked a lot about a schema and a querying that schema so immediately the first thing that came to my mind when I heard about it and it comes to everybody's mind is this sounds like some kind of a database it is not a database is simply a way to query your API you're not gonna change the way you code very much at all but it is it is easy to use a database as is a good way to explain what it is so I've got I've got some sequel over here shows creating a table you all know what that does and then over here I'm selecting some stuff from this table the equivalent down here is graph QL I'm creating a user type and it's got a user name and I'll get more into this later with graph QL as the name implies you're traversing a graph an object graph so I need a way in so this route is my way in so over here I'm executing a query it looks a lot like JSON it looks like basically the left half of JSON and then here's the response which is JSON so that's that's graph QL in a nutshell like you're basically making a schema it's got it's a type system that map's pretty closely to Scala not exactly but close enough and then some JSON out the other end okay so let's talk more about what these schemas can look like so the different types that you can create in schemas are you've got object types and fields so just starting here I've got a user type it's a user name it's got a string which is of type string there's an exclamation point after it that just means that it's not null so it's required I've got a comments field attached to this user so maybe I can fetch some comments this user created and it's in brackets that means it's a list it also does not have yet Meishan point that means it might be null if you get it if you query for that again here's my root it accepts arguments so think of think of this like a method on an object so I have a user method it accepts a username which is required and it will return a user down here you have this query and mutation so this thing is basically required in every graph QL schema it's basically saying this is how you get in so I have a query field and it's of type root so my way in is through the schema and I have a query field type root and then graph QL segments queries so reads from writes so it has queries and then mutations I'm not gonna go to too in depth into mutations so I don't have a ton of time but I and there's there's really nothing forcing you from side affecting inside the query nodes if you want cuz it's going to hit your code you can do whatever you want but you know you ought to adapt this model where only mutations happen through the mutation part of your query and of course read the docs to understand that more or talk to me after we've got some enumeration types interfaces these it's just like a trait you you can attach it to something and then you can ask for something of a type mammal and then there's some query syntax for how to treat data should it be a particular instance of that mammal so that's all there again not gonna go too into depth and then there's some Union types so these are all of your building blocks for creating a query that you can query against and express to your user in graph QL so how do I do it in scala so let's let's build a little test app here I've got a user and an avatar and an avatar repository that has a method called get avatar that accepts a username and returns an optional avatar and use a repository that has a method called get user that takes a username and returns an optional user so this very standard looking scallop code I'm gonna map it over to this schema here this is my graph QL schema you'll notice some differences my user does not have a field called avatar but I'm gonna add it to my schema so I'm gonna create an object graph I'm gonna have some things in that that you'll be able to traverse without having to call a service in this way so we're gonna explore how I add this thing my avatar is very straightforward it has exactly the same fields and then again here's my route so this is how I get into the object graph so I could I can basically just query for a user so that's the model and the schema we're gonna try and execute this query so basically I want to pull the user odor ski-out I want is username and I want the mobile-optimized URL so for his avatar so basically some low quality image that loads very quickly so roughly what I'm trying to say here is maybe I'm building an app for a mobile device and I don't want to get all the other data I want to get specifically the data that I need and then the query will look just like this so your graph QL I actually don't know if it's required that it returned data it might be it is if you use sangria which is the scala version of scala implementation spec and you'll get a field called data you'll get one called eros anyway it's just gonna return exactly that the data that you'd expect okay so I just wanted to start with here's some very regular looking Scala code it's everyone loves to hate the cake pattern I used it anyway because everybody knows how it works so there you go here's the cake I've got some I got a little database here with Martineau turkey in it and one for avatars than an implementation of my two different repositories to get the avatars out so very regular looking Scala code that you write every day and we're just gonna use that in our graph QL okay so now how do I map my different types into a graph QL schema so we walk through this very quickly already but I have an avatar I want to make this case class it's an avatar into a graph QL object type that is an avatar so this is the code to to perform that I parameterize it with two types I declare an object type I give it a cake which I'll use later I'm gonna explain more how the fields in the objects work on the next slide and then I give it another type which is the type this object is meant to represent and then here's my URL field it has a string type here's my mobile-optimized URL it's also a string type I have this resolve function in both of these and you'll see it I'm hitting this value argument which is pulling the fields off of this this this type of URL this I hope this come becomes more clear on the next slide this is how you create all the different object types to map your different case classes into graph QL and they'll look just like this so we saw this on a previous slide this is a lot of boilerplate so the preferable way to do it is down here there's some macros to very quickly whoops macros to do exactly the same thing in a single line and then of course there's there's ways to update those fields that are derived some more about fields okay so we created our avatar type on the previous slide now I want to do my user type but if you'll recall earlier in the talk I said I wanted to add another field it was called avatars so we want to traverse this graph avatars doesn't exist on my case class and users so I'm gonna add it myself and I do that I'm gonna derive the object with the macro but again because it doesn't have the avatar type I just need to add a field so to the derive type so I just add this in here again read the sangria ducks I hope I'd talk I may have passed over my slide about sangria sangria is the Scala implementation of the graph QL spec that was created by a guy named at easy angel on Twitter he's done an amazing job it's like an excellent piece of software anyway let's get back to this field so I'm adding a field called avatar it is a type Avatar object which was declared on the previous slide the field has this resolved functioned and I've given it a type I've annotated its type here just so you can see what it is it is of type context and then again is parameterised with the cake and the user because I am working with the user field and basically what happens is when a query hits your your server or whatever you're using to resolve these queries it's going to pass in context into this function when it gets to resolving that part of your query and you will then use this to build that particular part of your object graph so right here I've well it's worth looking down here at the context so this is what the context looks like there's a lot of interesting fields on it but the ones that you'll use the most are value CTX & args and value is again this parameter which is user here and CTX i've just it's my cake so all of the stuff that i need to get things out of my database or fetch them from wherever it's going to be in this cake so then when this function is called i'm using the context is populated with the things I wanted to just fetch my things out so I just think it was a cake that gets passed around I've never actually used just a straight-up cake in production we we have a thing we call a graph QL context it has a cakey like thing in it as a field but you could you can make it whatever you want so I don't know why we don't do this but I've often thought it would be great if we stuck the request object in there so if we receive an HTTP request we have the request if there were files in that request we could get the files out and for some stupid reason we just read the files out and then there's a file field that you can pull the file out but anyway so you make it whatever you want to pass in there so this is how it basically works and I hope that demystifies feels a bit how much time do we have one minute okay we're gonna do a demo okay this is called graphical you can see it good eye basically like a query analyzer that Facebook has put together you can basically load up a query and execute it against there and execute queries against a schema sorry you can load up a schema and execute queries against the schema so hacker news has a graph QL ski-in point and we're executing a query against it now what is cool is you can basically use this Doc's thing to just sort of figure out how to write a query so this is looks like I could I could query github so why why not let's see what miles Savin is doing github it's got all the query completion stuff you'd want user username I don't have this API memorized I just and you just don't need to which is cool you just kind of click around let's get his repos repos repo and let's get the names named and then run and there we go there are miles savings repos I I wanted to do this so maybe I should have even started with this I think this this to me is the selling point right here it's just all these tools exist on the front end for your developers every query they execute can be X it can be validated against this query I don't I don't even have to read the documentation on these api's I can just kind of use this query analyzer to figure them out we've had a lot of success with it we've been running it for six months if I had to if I could if I start it over I would do this again no no question yeah do it externally do it in your HTTP client and then stuff it into your graph QL context so you'll have a user stuff your user into that that that authenticated user into that object that I was passing around like my cake it'll just be a part of your your logic inside of the graph QL I can show you some concrete examples of how we're doing it I actually be interested to see how other people are doing it but there's actually a section on the sangria site to discuss it okay we gotta go but I will talk to you after all right thanks