DAVID:
I have this little pulse oximeter thing that I use to keep track of my bpm and oxygen and all that crap. And my wife just came in and stuck it on her finger and her heart rate leveled out. And then I kissed her and it went up six beats per minute. So scientifically speaking, I still got it!
[Laughter]
[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York, and L.A. bid on Ruby developers, providing them with salary and equity upfront. The average Ruby developer gets an average of 5 to 15 introductory offers and an average salary offer of $130,000 a year. Users can either accept an offer and go right into interviewing with the company or deny them without any continuing obligations. It’s totally free for users. And when you’re hired, they give you a $2,000 signing bonus as a thank you for using them. But if you use the Ruby Rogues link, you’ll get a $4,000 bonus instead. Finally, if you’re not looking for a job but know someone who is, you can refer them to Hired and get a $1,337 bonus if they accept the job. Go sign up at Hired.com/RubyRogues.]
[Snap is a hosted CI and continuous delivery that is simple and intuitive. Snap’s deployment pipelines deliver fast feedback and can push healthy builds to multiple environments automatically or on demand. Snap integrates deeply with GitHub and has great support for different languages, data stores, and testing frameworks. Snap deploys your application to cloud services like Heroku, Digital Ocean, AWS, and many more. Try Snap for free. Sign up at SnapCI.com/RubyRogues.]
[This episode is sponsored by DigitalOcean. DigitalOcean is the provider I use to host all of my creations. All the shows are hosted there along with any other projects I come up with. Their user interface is simple and easy to use. Their support is excellent and their VPS’s are backed on Solid State Drives and are fast and responsive. Check them out at DigitalOcean.com. If you use the code RubyRogues, you’ll get a $10 credit.]
CHUCK:
Hey everybody and welcome to episode 231 of the Ruby Rogues Podcast. This week on our panel, we have Jessica Kerr.
JESSICA:
Good morning.
CHUCK:
Coraline Ada Ehmke.
CORALINE:
Hi, hi.
CHUCK:
David Brady.
DAVID:
Oh, man. I just had a dream where a bunch of deaf people were heckling a mime.
CHUCK:
[Laughs]
JESSICA:
[Chuckles]
CHUCK:
I'm Charles Max Wood from DevChat.TV. Quick reminder, go check out RailsRemoteConf.com. We have a special guest this week, and that's Lee Byron.
LEE:
Howdy, y'all.
CHUCK:
Do you want to introduce yourself?
LEE:
Sure. My name's Lee. I work at Facebook on our product infrastructure team where I get to work on all sorts of cool stuff. But most recently I've been working on a project called GraphQL.
CHUCK:
Very nice. Maybe we should get a brief introduction to that as well.
LEE:
Sure. GraphQL is a way of moving data between clients and servers that we built here a little over three years ago. And it's grown in popularity since then at Facebook. And now it's the way that we build all of our mobile apps. And a little over a year ago, we decided to start to open source the chain of technologies that we use internally to build stuff. And chiefly among them was Relay, which is a really awesome user interface programming framework that leverages GraphQL for its data layer. So, you use GraphQL to say what data you need. And then you use React to say how you want to render that. And Relay ties all that stuff together. And we realized that open sourcing that without GraphQL doesn't work at all. It just is complete nonsense.
So, we had to figure out what it meant to take GraphQL which was this thing really tightly tied to all of Facebook and untie it. And so, that's what I've been busy with for the last 9 to 12 months. And we launched it open source about three months ago. And it's been a whirlwind since then. We now have GraphQL implemented in more than 10 different programming languages, only one of them by us. We open sourced a JavaScript reference implementation. And so, the communities picked it up from there. So, it's been really exciting. It's cool to see the progress, the community grow. I'm excited to answer your questions today about GraphQL.
CHUCK:
I think to start off, maybe we should start by giving it kind of a comparison to REST. I think most of our listeners as Rails developers are familiar with at least the way Rails does REST. So, what are the advantages or disadvantages to REST versus GraphQL?
LEE:
Sure. So, it's not quite an apples to apples comparison, because you can use GraphQL over REST. But typically once you start [taking it] down that path, you realize that most of the mechanisms you use in REST end up being replaced by mechanisms in GraphQL. What GraphQL looks like is a little query language, sort of similar to SQL that you send from your client mobile apps to your server. The ‘to the server’ part is where you start to overlap with REST. So, with REST you think about each bit of data in your mobile application as being an individual resource in your REST API. In GraphQL you still have these individual resources. We call them GraphQL objects. But they're allowed to link to one another directly rather than through additional URLs which is typically the way you'll see REST APIs do it. I know it's pretty commonly how you'll see Rails-based REST APIs illustrate links between these different resources.
The major breakthrough that we had with GraphQL is by specifying exactly what information you want, you can traverse from object to object, hence the graph part. We're traversing our graph of data. And get back in a single response everything that you asked for without having to do follow up. You know, I loaded that URL then I got this ID and then I got to go load the next URL, and then again another ID, and I got to go load the URL after that to do the deeply nested 'get my friends and then get the last few groups that they visited and then get the top 3 members of those groups'. You might find yourself doing multiple round trips. So, avoiding multiple round trips is one of the primary motivations for all of the work that we're doing right now.
CORALINE:
And since you're specifying which fields you want to get back, the payload can be a lot smaller than a REST-based implementation too, right?
LEE:
That's exactly right. So, there is no predefined payload response shape. We don't have an equivalent of a 'SELECT star' or something like that. You always say exactly what you want. Nothing more, nothing less, which is actually really nice because it means when you have your description of the data that you want right next to the UI that you're rendering, and you go and you refactor things and you delete a little bit of UI, you know really obviously that you can go and delete the data as well, because it's right there. And then your response size is going to be a little bit smaller.
And as you add new features, and this is something that's been really important to us at Facebook, is as you add new features that require new data, you can just add new fields in your query for that new data. And the endpoints don't send that new data to all of existing clients. So, we have now a little over a thousand different versions of the Facebook mobile apps in production use. We're seeing people regularly using them, including ones that we've launched three years ago, all of which use GraphQL, all of which have slightly different queries, and none of which break as we continue to develop.
And we don't have to muck around with version number checking, especially that code on the server can get pretty gross. Even Rails can't save you from the 'check the version to see if it's below this number' and then send that field, otherwise this field. All that stuff disappears, which ends up being really nice.
CORALINE:
So, you're basically implementing the best practice of extending an interface but not ever changing it.
LEE:
Yeah, exactly.
CHUCK:
One thing I like about this is that it helps you also avoid some of the stupid things that I see occasionally in people who start out with the boilerplate Rails scaffold or Rails page where it shows all of the fields. And so, it'll show, because it does a 'SELECT star'. And so, it comes back and it shows the password hash and the password salt or something like that. And it's like, yeah.
[Chuckles]
CHUCK:
It's all encrypted but it's still not a good idea. [Chuckles]
LEE:
Yeah. Did your application really need that and are you comfortable with someone sniffing your traffic seeing that?
CHUCK:
Yeah, exactly.
LEE:
Information. The other thing that's really important that GraphQL does, and this isn't necessarily counter to REST. In fact a lot of REST APIs also do this, is GraphQL is not really designed to tie directly against your database. So, it's pretty uncommon in a well-made GraphQL server that you would expose a password salt or a hash in the first place, because why is your mobile application requesting that? That seems nonsensical. And there are all kinds of other things. Like you have fields of information that are derived from other fields of information.
So at Facebook, underneath every story is a little sentence that says, “Chuck, Jessie, Lee, and five other people like this.” And we generate that on the server and it's of course generated based on fetching a bunch of other information and we don't store that line of text in a database. So, GraphQL maps against application code. Which means when you call into a field in GraphQL, when you query a field in GraphQL, you're actually calling a function on the backend rather than directly sending that as a query to something in SQL or MongoDB or something like that. And so, it eradicates that entire class of problems of 'whoopsie, I exposed fields from my database that I didn't mean to'.
CHUCK:
So, on thing that I'm looking at here, I have a ton of questions about this but one thing that I'm looking at here is that it seems like you could send all of your GraphQL queries then to the same endpoint. So, do you do that or do you have a different endpoint for say, fetching users versus posts versus likes versus pages?
LEE:
At Facebook we have one endpoint that serves all of our GraphQL and that's because the number of types that we can fetch just keeps growing. And adding different resource URLs for each would quickly get untenable as our applications would be fetching from all of these different URLs and trying to figure out what to do with them. Another nice thing that you can do is in a single query you can request for multiple things in parallel. And HTTP 2 and request pipelining can handle that for you at the network layer but it's nice to know exactly what shape of response you'll get from a single request. When you fetch three users, two pages, a group, and one other thing from a single endpoint.
And it also makes it transparent to the protocol that you're using to actually connect to the internet. So, whether you're using HTTP, whether you're using some push protocol like MQTT or something like that, you can keep using the same GraphQL query language and keep maintaining these properties of being able to fetch multiple things, being able to move from object to object seamlessly.
But GraphQL is built in such a way that you don't have to only have one endpoint. If you wanted to have 'this is the one spot we get all our users', 'this is the one spot where we get all our pages', you could certainly do that. And I've seen people build, I would call them hybrid REST GraphQL servers or maybe GraphQL mixed in with your REST. So, it's very much a RESTful service where you have a URL for every resource. But then you can select which fields of that resource you actually want via GraphQL. So, I think that's pretty interesting, too. And there are certainly some pros and cons to doing them each way. You get a little bit of the RESTful win of having one endpoint per, but just having a single endpoint ends up being pretty simplifying for your mobile client code.
DAVID:
Yeah. Do you have any security problems like protecting that endpoint? Because it seems like that endpoint is now basically a database prompt. How do you manage things like, say I'm loading a user but I'm just an end user so I don't want to see, I don't know, like hidden information, stuff that friends can't see on friends on Facebook. Like I can't see your gender, your date of birth, whatever. So, if I'm loading my record I can see it or if I'm an admin I can see everything. Is that meant to be handled elsewhere in the stack?
LEE:
Yeah. So, we handle that elsewhere in the stack. And this is actually a pretty important reason why GraphQL does not map directly do the database. And instead it maps to application code. So, presumably that means in your application code you are doing, we call them privacy checks, but permissions checks of some kind to make sure that whoever is logged in, into your account is actually allowed to fetch that information in the first place.
At Facebook we bake this into our whole application layer, which just removes the possibility for a mistake at any layer in our software stack regardless of whether it's a mobile client trying to fetch information over GraphQL or it's just something else that's happening on the server. If you load some information and that information, that exists in our application server's memory for you request, that meant that you're allowed to see it and it's now safe to use that information anywhere else in the system. Rails really has some nice parallels to this with its permission checking as well. So, if you think of GraphQL as something that can layer on top of Active Record and then you're using the same permission checks you would want to use with Active Record, then you're going to be in good shape.
DAVID:
Okay. So, I'm wondering if you can walk me through how the stack works then a little bit, because a minute ago I was thinking that, I'm looking at the Ruby GraphQL gem and it looks like it's structured so that you have some application endpoint that is backed by a Rails controller. And that controller then composes a GraphQL request and does the load and then renders it as JSON. But what you've just described sounds to me like maybe JavaScript is handing off a query meant to go to a controller. And am I reading that completely wrong? Where is GraphQL in the stack? Can you walk me through? Like I click on a button. What layer in the stack, how does that get all the way to the database and then all the way back? Is there a simple block diagram you can walk through?
LEE:
Yeah, I can talk through that.
DAVID:
Thank you.
LEE:
I can't speak directly to the Ruby implementation of GraphQL.
DAVID:
That's fine.
LEE:
Because I didn't write it.
DAVID:
That's fine. We have smart listeners.
LEE:
But I can tell you [inaudible]… smart listeners, you guys can figure this out.
DAVID:
Yep.
LEE:
So, GraphQL is one of these interesting pieces in that it fits between the server and the client in the stack. So, there's a little bit of stuff happening on both sides. Most stuff is happening on the server, though. So, the client's responsibility is really just to assemble this query. And you can do that manually by writing out the whole query. You could do that using a tool like Relay which lets you write queries in lots of tiny little pieces collocated to your UI and then it will assemble them up for you into one query. And it'll do that in a smart way. And then that gets sent off to the server. So, the server, it gets a string of text. It parses that. So, you have your typical compiler frontend stack here where you have this string of text in, you parse it, you make sure that it's actually valid GraphQL, and now you have an AST. You take that AST that represents the query, and now we can do cool stuff with that.
So, we can walk over that AST and we do something called validation. So, we walk over the AST and we basically say that every field that you've asked for is a field that exists. Everything that you asked for is unambiguous. So, there are some things that could be syntactically correct but ambiguous and we make sure that you can't actually submit a query that looks like that. And once that has gone through and we say “Everything checks out, this query looks great,” then we run it through a piece of the stack called the executor.
So, the executor takes in this AST that represents your query, steps over it from the top all the way to the bottom in a depth-first each kind of traversal. And every time it gets to a field, it looks into this thing that you define on the server called your schema. And the schema is just a way of describing every kind of type in your server. And these mentally at least map really well to Active Record classes.
DAVID:
Right.
LEE:
And each field is a property on one of those. And when you call into one of these fields, when you request one of these fields, the executor will look into your schema and say, “What function should I call for this?” And you actually provide a list of functions. Whether the library does this for you, and often that's actually the case, or you're actually providing a lambda function or something to actually do this on behalf of GraphQL, you're providing tons and tons of tiny functions. One function for every field of every type in your system. And so then, once you're in a function you can really do anything. But what's pretty common is that you, the first argument to the function is going to be the object that you're interested in. And you're probably just going to do a property lookup.
So, 90% of GraphQL fields look like that. And then some of them have to say, “Oh, I need to go get that from a database.” And so, that might map to Active Record needing to load up a new object and it's going to under the hood execute a SQL query. But GraphQL itself is never, doesn't really know anything about SQL or MongoDB or any other database backend. It just knows about calling functions. And so, it's up to you to provide the appropriate functions to map between the query and the data that you need. Does that make sense?
DAVID:
Yeah.
LEE:
We can dive into the corners if there are more questions.
CHUCK:
Well, I definitely see the advantages here because then what it does is it divorces a little bit the logic of figuring out what data I need from the actual connecting to the database, which are two different concerns legitimately. And so, you get this clean separation of concerns which we don't always get with Active Record since everything piles into the model in a lot of cases.
LEE:
That's true. Yeah, that's definitely true. What you end up seeing in that executor is this top-down querying. So, if I were to say, “Get my user object,” it would want to go to the database, request that user object, come back. And then I can access fields. I can say, “Give me the name of that thing.” And it's going to assume that when we fetched from the database, that it had a name property on the resulting row or Active Record object or whatever, and I can just access that property. But as soon as I dig deeper and say, “Well, who's my best friend?” then that's probably going to, it might be an ID in the Active Record or database row and I'll have to go back to the database to load that information.
So, it divorces as you were saying, it divorces the actual mechanism of going to the database from the information you need such that it's requesting these information but it's requesting them in dependent waves. So, all the information that it's capable of requesting in one go, it'll go to the database once and get all that information. But if there's dependent information, like I can't know the best friend of me unless I know who I am first so I got to fetch that, and then later follow up with the second query. So, divorcing these two things means that you end up writing far fewer join query operations.
DAVID:
So then, it sounds like, well I'm sorry. It sounds like by which I mean you've made it very clear [chuckles]. GraphQL then does not [end] run around say, Active Record. It stops at the border of the database and then says, “Active Record, I want you to go handle these things.” And so then, all these functions that you have to resolve fields and build queries in a Rails application, that would be some layer that you've written that would basically say, “Okay, here's how we translate GraphQL into Active Record.”
LEE:
Right, exactly.
DAVID:
Okay, okay.
LEE:
That's exactly right.
CHUCK:
So, one other thing that I'm seeing here is that then there is a GraphQL implementation on both the backend and the frontend?
LEE:
Critically, you have to have a GraphQL implementation on the backend, right? So, you have to have a way to respond to these queries.
CHUCK:
Right. But you need something on the frontend.
LEE:
On the frontend you have a lot more flexibility. That's like saying, “Do you need a SQL client for your frontend?” It might add some convenience, but at the end of the day you can always just write a string and then send it to the DB and get a response back. So, it behaves similarly to REST in that you load a URL with this request and it comes back with JSON. And if you're comfortable assembling these query strings yourself and taking that JSON and just using it, then you're good. You're off to the races. But you can get a little added value by having some nicer tools to use on the client. Relay is the one that we use internally for our JavaScript frontends. We have other tools that we use for our iOS and Android apps. And we're actually working now to untangle those from Facebook specific-isms so that we can open source those as well. They just add some additional cool stuff that you could do.
One of the really nice things that you can do is since GraphQL describes these types, these strong types of query language, we can ahead of time ask for all of the possible types and then on the clients we can do auto-generation of model objects, auto-generation of fast parsers, and autogeneration of a couple of other artifacts that you would want such that the people who are actually using these things don't use them as “Oh, I have untyped arrays and objects that are just my raw, parsed JSON.” Instead they have rich model objects. And they never have to actually write that code. We can auto-generate that code for them.
CORALINE:
I have a question about the type system. I'd like to be able to talk about the decision to make it strongly-typed. And also, what sort of implications does that have for the server side that it is a typed system?
LEE:
Sure. So, the reason that we wanted a strongly-typed system here, there are a couple of reasons. One is what I was just talking about, the ability to take that information, carry it to the clients, and then do useful things like code generation. Another is validation. So, a lot of database query languages are also strongly-typed. So, SQL is strongly-typed. If you try to ask for a column that doesn't exist, it will yell at you that you can't do that, right? And each column has a particular type further in. An interesting thing that we've done beyond SQL is more than just scalar types. We can say, “Oh, this is actually a pointer to that other kind of type.” So, our type system looks and feels much more similar to maybe C structs.
On the server what this does is it means that you can have a clear guarantee that a query coming in is never going to ask for something that you didn't explicitly define. So, because you defined, “I have this set of fields that are all just raw property getters, and then I have these handful of extra fields that are lambda functions that when they come in I'll run my function and get some value back,” I know that that is the total set of all possible things that can happen, which means I can make guarantees for safety. I can make guarantees for performance. I can make guarantees for server stability that I otherwise couldn't if I said any arbitrary field that comes in, duck type it and see what works.
CORALINE:
Does that create some implications for reserving the API though? Like if you need to change a type for whatever reason? Or is that just something you just don't do?
LEE:
Oh, that's a really great question. Yeah, so this is how we do versioning. So, consider this. We launched GraphQL three years ago. And we're using the same version of GraphQL, the same type system today that we were using three years ago. And if you boot up a version of our iOS app that we shipped three years ago, it'll still work. So, we don't use version numbers. And basically that means that we can never delete any field that we've shipped. In order for everything to stay working that's shipped before, your type system has to remain additive only.
So, when we want to add new things, we just have to make sure that we're adding things in a way that doesn't conflict with something that already existed. And if you want to change the type of something, which actually in practice happens pretty rarely, it's been three years and I field a lot of the questions from Facebook engineers about how we should operate around these things. And I get, “Oh crap, we need to change the type of this thing,” maybe once every two or three months. And actually, most of the time that it comes up, what is happening is they haven't actually shipped it yet. So, they're working on their product and they haven't launched. And they realized that they made a mistake in their API layer and they want to fix it. And you know what? Okay, fine. Technically, you're breaking the API but you're only breaking it for the people who are testing your app internally. That's fine. Once you've shipped it, no you can't change that.
So, if you want to change the type of a field, what you end up doing is adding a new field with the new type that you want. And you just maintain the behavior of the old field. We have a mechanism we can use for deprecating fields. So, if you're using them somewhere on the client, we'll squiggly underline them and say, “Don't use that. Use this instead.” And that way, progress can move on.
We can keep using new fields, new types, everything new, but only ever adding to our API design.
CHUCK:
I find it interesting that you've gone with this type safety situation where GraphQL at least on the frontend is running in JavaScript which is not a strongly-typed language. And in our situation on the backend with Ruby, we're also not in a strongly-typed situation. So, [chuckles] I'm assuming then that there's just some class checking or other sort of interface checking to make sure that it is what it says it is.
LEE:
So, we actually have a type checking mechanism built into the GraphQL semantics themselves. So, we don't actually need a host language that has strong typing. If your host language does have strong typing, then you can do some pretty interesting things where you tie the two together and that can make some of the work involved of actually defining your GraphQL server.
CHUCK:
David just pointed out, and yes I used the wrong term but I couldn't think of what the right one was, he says Ruby is strongly-typed but not statically-typed.
LEE:
Yes. And…
CHUCK:
That's what I meant, is a statically-typed language.
LEE:
And GraphQL's actually kind of similarly so. It's actually pretty similar to Ruby. So, there are some nice things that you can do with Ruby classes. I don't know if we've implemented all of the cool ideas that we've had for Ruby in particular with GraphQL. I'll have to go chat with the guy who's working on GraphQL Ruby about that. But I know he's already done a bunch of the nice 'we'll do some of the boilerplate-y work for you since Ruby has some of these things built in'. But our reference implementation is in JavaScript as you said. We use GraphQL on the client in JavaScript with Relay. But we also use GraphQL on the client in iOS and Android which use Objective C, Swift, and Java, which all have types in their languages.
So, having the semblance of typing but not requiring the host language to support it directly gives us the ability to have a best of both worlds approach where if the clients want the types, they have them. If they don't want the types, then they just have JSON. And for the servers that are hosting this stuff, you have to spec the types regardless of whether your language supports them or not such that the clients have these capabilities. And if your server does support types, so at Facebook we use Hack which is a future derivation of PHP, and the Hack language is full of strong types. And we use those to make the process of adding new GraphQL fields and types much, much simpler.
JESSICA:
Are they more like contracts than types, really?
LEE:
That's a perfectly fine way to think about it as well.
JESSICA:
Since they're checked at runtime, at least in some languages. Because the GraphQL language itself, it looks a little bit like JSON, right? Curly braces and words.
LEE:
Mmhmm. GraphQL, yes. The queries themselves, there are a handful of places where you'll see a type name show up. But most of the time, we are inferring the type. So, it's still a statically-typed and strongly and statically-typed from the queries point of view in that when you submit a query, before running the query we can tell you if you asked for a field that doesn't exist on a type. And we can do that because since every field has a return type, and then the next set of fields query against that return type, we can walk that all the way down. And if one of those returns a type that's an interface or a union, say, then we'll make sure that the fields you're requesting are first… first you do a type check before you do that.
And we have a mechanism for doing that called inline fragments, which lets you say, “Hey, I'm going to fetch something and I don't know what it is. But it has this ID.” And there are some places where that happens. So, you mention something in a comment. You can mention groups, you can mention users, you can mention pages. They're all mentions. And in the query we'll say, “Okay, well we want the text of that mention,” and we can get that uniformly across everything and that's in the type. But I can't say, “Get me the profile picture of that thing,” because I don't know if it's a profile. So, first I have to say, “Are you a profile?” And if so, then get the profile picture.
And that will guarantee that only on that type will I request that field, which limit ambiguity spots or over-fetching when something that's not a profile but somehow miraculously specifies a field with the same name, all that stuff disappears when you can statically type check these things first. But it definitely is a contract. That's the whole point, right? API is a contract. And having that contract be stable through the constant iteration of the server and the client, that's the crux of the whole thing, keeping things stable as to their contracts.
JESSICA:
Yeah. I love how GraphQL is naturally backwards-compatible just because it's so declarative.
LEE:
Yeah.
JESSICA:
The client says, “I want exactly this,” and the server doesn't have to count versions or anything. It just gives it exactly that.
CHUCK:
Yeah.
LEE:
Yeah. And it makes implementing it much nicer. The first time you implement a REST-like API that needs to do version-tracking it feels great because you're not actually doing any version-tracking yet. But if you have ever had to work on a REST API that's more than two or three years old and that product went through lots of iterations and grew and added things or removed things, then you're in for a headache, right? Because you have to check versions on every single little thing to figure out exactly what to build. And it can be really a pain to maintain that thing.
DAVID:
Yeah. I worked at a… actually, Chuck and I worked at CrimeReports together and we had a case where we had to expire a contract. And I like contract in this case, because we had to expire it like in a very legal sense where a customer called us and said, “You are giving out a piece of information here that you cannot be giving out.” And this company was called CrimeReports and our customers were law enforcement agencies. So, when they say you have to stop giving out this data, they don't say, “Or we'll call the cops.” They say, “Or we'll call us.” [Laughter]
DAVID:
And there's ways to work around it. But yeah, I like what you're talking about where you avoid the versioning hell of you get a request and you're like, “Oh, is this version 1, version 2, version 3, or version 4? Because we're going to support them all differently because there's different logic in 3,” and that sort of thing. Having things fall off the backend, like we had to make version 1 go away. And so, we just added a little bit to the iOS app that it would just come up and it would just check the version very early on. And if the version was pulling down this data that it couldn't have, you would just get this immediate dialog that says, “This version of the CrimeReports app is no longer current. Please update the current version from the app store.” And they had to go do another quick download. And that way, we had two versions that we had to support. Because anything older than that, we just deprecated.
LEE:
Yeah. So, we can turn off individual fields and we've done that before, where we're building some product and then we'd realize down the road that some element of that product is doing something that it shouldn't and is old and what we really want to do is just turn it off.
DAVID:
Yeah.
LEE:
And it's a bummer if you had to say, “Oh, you're using this slightly ancient version of this application and we're just going to force you to upgrade.” Well, there's actually a bunch of circumstances where that's not possible.
DAVID:
Yeah.
LEE:
If you're on an older device that is limited in bandwidth or limited in hard drive space and your app… like, we've had circumstances, and this is maybe a Facebook problem, where the hard drive space of the mobile phone is less than 2x the size of the binary required to run Facebook.
DAVID:
Right, right.
LEE:
Which means once you've downloaded Facebook, you can never update Facebook because you can't keep the current binary and the updated binary in memory at the same time to actually perform the update. And so, those people are basically stuck until they get a new phone sometime in the next few years. So, we basically commit to maintaining very old versions of our apps.
DAVID:
Yeah.
LEE:
But what it means is when you want to kill off one of these fields, we make the assumption that almost any field can return back null. And so, we program pretty defensively on our clients against that as well.
DAVID:
Yeah.
LEE:
Which ends up being nice when you want to do something like that. So, say we were building a GraphQL version of CrimeReports and you're like, “Uh oh. This one bit of information is bad. We should not do that,” you could go in and find the one function where it's doing that and just comment out the implementation and type in 'return null'.
DAVID:
Yeah.
LEE:
And you would just be done. And it didn't matter if, do we remember, was that only version 1 or was it versions 1 through 7 or I can't remember.
DAVID:
That's cool.
LEE:
It's just like, it doesn't matter which versions of the apps are creating that. That field is now gone.
DAVID:
Yeah. That's actually really awesome. Building the client forward to be fault-tolerant turns out to be essential either way. You either have to be able to handle a null field or you have to handle this version check, because we really did have some version 0 apps running out there on iPhones that did not check versions. They just tried to grab the data and they would crash.
LEE:
Yeah.
DAVID:
And we would get support calls and we're like, “Yeah, you got to upgrade to the new version which will tell you to upgrade to the even newer version.”
LEE:
[Chuckles]
DAVID:
And [Chuckles] I like this GraphQL notion of you could actually change the function so that every time you hit that field, instead of you getting back 'no data', you get back 'unknown' or you get back 'no longer available' or 'n/a'.
LEE:
Sure.
DAVID:
You could actually send back data.
LEE:
Yeah.
DAVID:
Or just an empty string.
LEE:
Yeah, totally.
DAVID:
And, yeah. That would be very cool.
LEE:
And it's a one-liner to do that. There's no, “Oh, we got to add these version check logic and do this.” It's like, no you just go like, there's this two-line function that describes that bit of information and we just changed it to return some static bit of information that is not going to cause us legal problems or whatever.
DAVID:
Yeah.
LEE:
In your case. The other thing that's kind of gnarly about versions is our mental model for versions is often that they're linear. You get version 1, 2, 3, 4, 5, 6, 7, onward.
DAVID:
Right.
LEE:
But in practice, version numbers fork and fork and fork and create trees.
DAVID:
Yes.
LEE:
Which makes checking them pretty difficult. So, before GraphQL we had something that looked much more similar to RESTful API service. And for a while, really our only native app that was consuming this was our iOS app. This was years ago. And the big news that happened is that Android launched and started to get popular. And so, we built an app for that. And now we have these two things running in parallel. But they're not perfect ports of one another.
In fact, there are some features that are Android-specific and some features that are iOS-specific that take advantage of the features that those OS's provide. And that means that the payloads of information would need to know not just this progressively counting up number of version but like, are you iOS or Android, and then what version are you? And now, we also have Windows Phone, and we also support a couple of other platforms. And so, you have all these fork points. And then you split by product. So, we have not just Facebook but we have Messenger and we have our ads management applications and we have over a dozen different applications. And then each of those runs across each platform. But they all request similar information about…
DAVID:
Yeah.
LEE:
Facebook users and what they're connected to. And so, you end up with this huge forked version tree. And some of that is just that we have a number of products and we make sure we support all of our platforms. But you know, most shops that are building native apps that hit a server support most platforms. And often they have more than one product. So, this is a thing that happens.
DAVID:
Yeah.
LEE:
Checking those versions at the server, it gets gnarly. It's really hard to maintain.
DAVID:
So, I've got a related question to that. I'm currently working at CoverMyMeds and I love it and we're hiring, by the way. Plug. [Chuckles] And we're in a situation that I call dancing with the elephant where we're working with really big healthcare companies. But we'll have one client that will use our REST API. And they want to use it just exactly straight up the way it is in the documentation. But we have this other client that, oh let's see, I can't say anything negative about our customers. Well, let me just say we have a client that is using our REST API in a different manner. And they are so big that it was easier for us to just change the way our API works for them. So, we actually have some conditional code that says, “If this client is client X, when you retrieve this field, munge it in this way.”
CHUCK:
[Laughs] Oh, man.
CORALINE:
That sounds nightmarish.
LEE:
Okay.
CORALINE:
Oh my gosh.
LEE:
Yikes.
DAVID:
Yeah. It is nightmarish.
LEE:
[Laughs] It's crazy.
DAVID:
But it's the kind of nightmare…
LEE:
That happens though.
DAVID:
Yeah.
LEE:
Actually some of my favorite technical warts are these special cases in operating systems that work around the mistaken use or forceful use of APIs in a way that they weren't originally intended.
DAVID:
Oh, yeah.
LEE:
And cause issues. And then the OS upgrades and makes new versions and they realize they have to continue to support those weird versions as they existed.
DAVID:
Yeah. The particular wart that I'm thinking of, it's a multi-million dollar wart, right? I can fix that wart.
But a couple of million dollars a year of revenue will walk out the door as soon as I do. So, we're happy to have that wart. [Chuckles]
DAVID:
We're happy to have that.
CORALINE:
That's something I never thought I'd hear anyone say.
CHUCK:
[Laughs]
DAVID:
You know what?
CHUCK:
You can freeze them off.
DAVID:
In 'Freakonomics' they found out that about 10% of people are incorruptible no matter how much you tempt them or how guaranteed they are to get away with it. They will not cheat in whatever they're doing, whether it's remembering to… I'm not going to refactor my code, or I'm going to actually steal money, or whatever. In the case of Sumo wrestling was the specific case where they discovered this. 5% of the population are incorrigible.
LEE:
[Chuckles]
DAVID:
No matter how little the payoff or how guaranteed they are to get caught, they will cheat.
LEE:
[Chuckles]
DAVID:
The other 85%, we have a price. [Laughter]
DAVID:
And that's what he determined, is that everybody else, there is a price point at which the value of the reward and the likelihood, the minimal likelihood of not getting caught, is enough that we will cheat. And so, when I say everything is a trade-off, what I'm saying is I'm for sale. I'm one of those people that I know… like Calvin and Hobbes, right? “Everybody has a price. Mine's 75 cents.” [Chuckles]
DAVID:
And yeah, it's like you want this wart that's going to make it so that we can interact with the number two or three largest player in the healthcare informatics field. Okay, here's a wart. That's not a defect. That's a feature.
JESSICA:
Yeah, I would rather my code be useful than right.
DAVID:
Yeah. I'd rather my code make money than be useful or right. [Laughs]
LEE:
I think the trick is just calculating the trade-off. Because there is a maintenance cost to that wart.
DAVID:
Oh, yeah, yeah.
LEE:
And you balance, well how expensive is the maintenance cost of this thing? And if you realize that, oh that poor sucker is not paying us nearly enough to keep this around, then you're going to force him out of his ways into doing things the correct way and you'll fix the wart.
DAVID:
Yeah. Or you'll canonize the wart and make it the right way.
LEE:
[Chuckles] Or you'll canonize the wart. But then, that means canonizing a maintenance cost as well.
DAVID:
Yeah. When I say canonize, what I mean is you make it the official way. And so, you streamline the maintenance because it now becomes the happy path. And the people that are using it the old correct way, they now become the special case and we try to… you know what I mean?
LEE:
Yeah.
DAVID:
Canonizing the wart is where you like wean the people off that you thought were the right users and that kind of thing. Yeah, which actually leads perfectly to my next question, which is how can we do this with GraphQL? I've got two different clients that are accessing the same thing. We don't have versioning. We just have different data types. Is there a way that I can make it so that in one context, a field comes back one way but in another context, comes back another? Or is that just stupid and wrong and I should have two different named fields and somewhere else in my application I should just pick which field I want?
LEE:
So, of course the answer is that you can do anything, because computers.
DAVID:
Sure. [Laughter]
LEE:
But I'll bring it back to the maintenance costs argument.
DAVID:
Sure.
LEE:
And the thing that has the least maintenance cost is to have different fields with different behaviors.
DAVID:
Okay.
LEE:
And the reason that the maintenance cost is less is actually a little bit maybe surprising. It's not necessarily a maintenance cost on the server. It's about the predictability of your API. So, what we found… we have cases like this because we make mistakes and we go, “Oh, shit. Let's just hack in on the servers to make it work.” So, the same kind of deal except instead of a major client you don't want to lose money from, it's ourselves that we're shooting in the feet. So, we'll do that. And then we'll forget that we have added that server hack to make that client still work.
And then that client will become large and popular and will have more developers. And then a developer will start to investigate a problem. And they'll be confused as to why something is happening. And then they'll copy their query and they'll go over to the website and paste it in some tools to help debug that query. And then they'll get wildly different results. And they're like, “What's going on here?” And it turns out, well the thing that someone had done to “hack around it” is, they could do anything because computers, and so they took the user agent header and did sniffing on that. So, they just reached out into global space.
DAVID:
Ah, yes.
LEE:
Grabbed that header, did sniffing, and then changed the behavior of a bunch of fields based on whether or not your user agent was coming from this particular application.
DAVID:
Right. You're running IE6, so we need to make everything look like crap.
LEE:
Yeah, exactly.
DAVID:
Yeah, little known fact. The internet looks just fine on Internet 6. It's just everybody has a flag. We've just all conspired to make it look awful if we detect that you're running IE 6. [Laughter]
LEE:
That's definitely not untrue.
CORALINE:
I thought that was a feature.
DAVID:
Mmhmm, mmhmm.
LEE:
It is kind of a feature. And so, that ends up just being really confusing for people who are having to use the API when they use it in one context and it works differently from when used in another context. And it is unclear as to what variable changed because headers are relatively invisible to your clients. They don't usually think about, “Oh, of course I'm also sending headers along with my request.” And actually, something that ended up causing us trouble is when we added new avenues for fetching GraphQL other than HTTP. We realized the hard way that these other avenues didn't have headers. And we were using those headers to do logic. And now that we're sending them over push channels and things like that, all of a sudden these old clients start to break.
DAVID:
Yeah.
LEE:
And so, we had to come up with this gross hacky way of adding headers to push channels for those specific things. And it was gross. So, avoiding that and doing it the, maybe it makes your API slightly uglier, but the maintenance cost is going to be much lower. But of course, yeah, you can do anything with computers.
DAVID:
Yeah. Okay. So, one last quick question and then Chuck has another direction he wants to take us. But in GraphQL can I structure a field to be a derived field off of another field? To give an example, like this client where we have this wart, right? I'm going to make something up just to protect myself from the innocent. Let's say most of our clients expect phone numbers to come back as 10digit decimal strings. This other client expects 3 digits, a period, 3 digits, a period, and 4 digits. Clearly we can derive one field from the other. Can I tell GraphQL to do that, to give me two fields where one field is calculated off the other? Or does the data come through GraphQL all in one layer and there's not necessarily a self-introspection layer. Like you may have a [inaudible] problem where you can't derive from a field that doesn't exist yet.
LEE:
So, to answer your question in the broadest sense, you absolutely can have two fields where one is a derived information from another. And in fact, that's a very common case.
DAVID:
Cool. Okay, cool.
LEE:
To be more specific, you can't have GraphQL query itself while running.
DAVID:
Okay.
LEE:
Because it can create some kind of badness of [inaudible] loops and stuff like that.
DAVID:
Sure.
LEE:
But because each field is backed by a function, presuming that both of those side-by-side fields have functions that have access to the same information, then this becomes easy. So, say I don't know, it's a phone number of a contact. And so, a contact is your model object, Active Record, whatever. And the phone number 1, it's going to be the identity function version of get the phone number, which is it's just going to access the property and then call it a day.
DAVID:
Okay.
LEE:
For…
DAVID:
The data's all there for the entire record before the functions run?
LEE:
Yes.
DAVID:
Okay, yeah. That makes sense.
LEE:
So presumably, one level sooner you would have said, “Get me this contact,” and it would have gone to the database and gotten the whole contact row.
DAVID:
Right.
LEE:
And then [one] step later say, “Now I want the phone number,” and it's just going to grab the already fetched column from the row that you just got.
DAVID:
Perfect.
LEE:
If I want phone number dotted as another field, I could provide that as a lambda function and say, “Okay, model object in, what do you want?” And it's like, “Ah, actually okay. I'm going to get phone number and then I'm going to pass it into this weird function that does dots and dashes and [parentheses].”
DAVID:
Right, right. And because your functions are also loaded in memory, they can actually call each other as long as they ultimately go back to the data which is now loaded. So, you could have a phone number with extension that calls phone number dotted, adds a hyphen, and then goes to the model and says, “Give me the four digit extension”.
LEE:
Totally.
DAVID:
Okay.
LEE:
Once you're calling a function, you've got your entire programming language to flex, which means you can really do a lot.
DAVID:
Okay. I've been holding out on this but GraphQL now gets my seal of approval because it sounds freaking awesome. [Chuckles]
LEE:
Yay.
CHUCK:
So, one question that I have, the way that I heard about GraphQL initially was through Relay and React, which are both JavaScript libraries. And so, I'm wondering, was this ecosystem built up around Relay and React and then extracted from that? And if so, what assumptions have been made about the way this works based on Relay and React? And then I've got another question to follow that up with.
LEE:
Okay. So, yes and no. GraphQL was originally built before React was ever invented. So, it was built to support our iOS and ultimately Android application. Android followed by about six months. But we developed GraphQL explicitly to build a much better iOS application. So, it was really built with iOS in mind first. We followed on with Android and we found and fixed a handful of minor assumptions that we had made about iOS. And between those two platforms, it was really generic. React came about a year later. So, we've been living in the age of React for the last two years or so. And Relay is about one and a half years old within the company and only a couple of months old in open source land. And Relay is about tying together GraphQL and React.
So, we were envisioning, how could we build Android-style applications but use JavaScript and React Native is one of the pieces that came out of that. Relay was another one of the pieces that came out of that line of questioning. And then as those pieces of technology raced towards open source, we realized that GraphQL had to go with the rest for that whole suite to make sense because they used GraphQL. So, in that sense, yes. There's certainly an ecosystem that's starting to form where these technologies… well, usefully, while being useful independent of one another, clicked together nicely to create a horizontal platform of technologies that work well together. And so, they really had to go out close to each other. Or Relay and GraphQL in particular had to go out close to each other to make sense.
CHUCK:
I guess the other question then is, can I use Relay and/or GraphQL with something like Angular or Ember or Backbone or something?
LEE:
GraphQL, absolutely. You can definitely use GraphQL with any of those things. If they are capable of sending a network request and capable of handling JSON then you can use GraphQL with them. Relay is very, very tightly tied to React. So, you can't use Relay without using React. In fact, by using Relay you're definitely using React because it's how it is built.
But there's lots of really cool work that's being done in those other frameworks to make things that work similar to Relay where you specify the data that you need directly alongside the components that you're loading. And I'm forgetting the name of them. But we recently had some chats with the Google folks working on Angular too, who are coming up with all these similar ideas that we were having for Relay. And that made us excited that we're running in parallel on these thoughts. So, the concepts at least are jumping outside of the software that we've written. And hopefully, I would love to see GraphQL become a common point along a lot of these things. That would be awesome.
CHUCK:
And GraphQL when I first heard about it I was like, “That sounds weird.” And then we had that conversation with Nick and Joe and it was like, “Okay, this is something I really got to dig into.” [Chuckles]
CORALINE:
Yeah. I think it makes so much sense.
CHUCK:
Yeah.
CORALINE:
I only learned about it just doing prep for this show. I think I heard about it before but never really understood or never dug into it at all. But after digging into it I'm like, “Wow, this is really cool. And I want a project where I can use this.”
CHUCK:
There's a very similar system called Falcor by Netflix.
LEE:
Yeah, yeah, yeah. [Inaudible]
CHUCK:
And it's got a lot of the same ideas behind it.
LEE:
Mmhmm. It makes slightly different trade-offs.
CHUCK:
Yes.
LEE:
But they have the same basic goals.
CHUCK:
Yup.
LEE:
One of the really interesting trade-offs that they make differently is about bandwidth concerns. So, with GraphQL we're trying as much as we can to make as few round-trips as possible and to really pack in as much information in each round-trip because we're servicing mobile clients that are out there on shitty networks. Netflix assumes that you're plugged in, into a TV where you're about to stream some HD content. And they assume that your latency and bandwidth are very high. And so, that ends up with pretty different trade-offs but it's pretty interesting to see how that ends up changing your system.
But the whole idea of you have information on the server, you need to get that information to the client to use it in your views. How do you do that? We've come to very, very similar conclusions on that, which is super cool. It means that we're onto the same technical zeitgeist I guess. Our teams have chatted with each other as well. And so, that's always exciting.
CHUCK:
Yeah. Jafar gave a talk on Falcor at Angular Remote Conf. And I was just sitting there going, “Oh my gosh, oh my gosh, oh my gosh.” And then part of me went, “Isn't this kind of like GraphQL?” [Chuckles]
LEE:
[Chuckles] Yeah.
CHUCK:
Yeah.
LEE:
Similar problems to solve, yeah. And even similar solutions.
CHUCK:
Yeah. Yeah, very much so.
CORALINE:
Did they open source Falcor?
CHUCK:
Yes.
LEE:
Yes.
CORALINE:
Okay.
CHUCK:
Yeah, and they've mandated… they're much more of the opinion that you should only have one endpoint.
LEE:
Yeah. I think that's probably for the best. One endpoint makes a lot of things much simpler.
CHUCK:
Yeah. Yeah I don't see it making a lot of sense segmenting by your types of data. I might see it make a little bit of sense if you're dealing with different access levels or something.
LEE:
So, we think about it as different access points for different type systems. So, we have a different type system for Oculus. So, Oculus uses GraphQL. And they have a completely different type system. And so, we have a different endpoint for them.
CHUCK:
Oh, that can make sense.
CORALINE:
It's nice [inaudible] versioning.
CHUCK:
Mmhmm.
LEE:
Yeah.
CHUCK:
Because you're thinking about the data completely differently.
LEE:
Yeah. Because it's not really… And there's a little bit of overlap. Like Facebook users flow through in some respects because you can see 'friends who are playing this game'. And so, there's a little bit of overlap. But because it's so different it just makes sense to think of it as a completely different source of info.
CORALINE:
Cool. Lee, you talked a little bit about the origin of GraphQL. If you were creating GraphQL from scratch today, what do you think you would have done differently?
LEE:
Oh, that's such a good question. So, we totally GraphQL from scratch again when we open sourced it. And I got to do that exact experiment. So, GraphQL three years ago and GraphQL open sourced as of three months ago look pretty different from each other, actually. When we first built GraphQL three years ago, we built it fast. We did not realize that it was going to be a really important thing to how Facebook worked. It was really like an iOS news feed specific piece of technology. And we built it in a month or two and then just moved on. And as other teams started to use it and use it in different ways, we started to see all of the different use cases for GraphQL. And at Facebook those have started to feel patchy and inconsistent. So, when we decided to open source, realized that was our last real opportunity to make significant changes to the language. And we took that opportunity.
So, we had a couple of months where we went back to the drawing board and said, “How much of this stuff is accidental and incidental from what we originally decided? And how much of this should continue on?” So, the idea of the nested layers of querying and the idea that fields can have additional metadata sent to them, in the open source GraphQL we call those field arguments. In the Facebook version of GraphQL we call them field calls. Similar client functionality. And we've simplified the language itself. So, what you see when you write GraphQL in the open source version is just much nicer to look at and simpler than what we're using internally at Facebook. And actually, what I'm working on now is taking all of these improvements that we made that we launched in open source and making sure that we're folding all of them back into Facebook so that we're using the same version at Facebook that people are using outside of Facebook.
CHUCK:
I'm really curious. Are you moving to React Native for your mobile apps?
LEE:
We use React Native in a bunch of our mobile apps. So, in different capacities. I don't think that we will ever have React Native as 100% of all of our apps. It's not the right technical decision. And actually, an important cultural detail about how engineering works at Facebook, we build these tools like React Native and Relay and GraphQL. But the teams that use them, it's entirely up to them as to whether or not they use these tools or use something else. So, if you're working on a new product at Facebook and you decide that Angular is the best technical choice, great, use that. We're going to build these things because we think that they'll be useful for you. And we will help support you as you use them. But ultimately, if it's not the right technical choice then go use something else. Which means for our native development teams, they have a suite of technologies they can use. They can use of course Objective C, they can use Swift, they can use React Native, they can use blends of these things, as is most beneficial for what they're building.
So, our ads manager is 100% React Native. And that's because they were building in parallel the new version of the ads manager for the desktop and the ads manager for iOS. And then once they finished iOS they got started on Android as well. And between the three platforms, web, iOS, and Android, about 85% of the code is completely shared. And the remaining 15% on each platform is platform-specific user interface and logic. Our groups, we have a standalone groups application. And that's about 50/50. So, about half the views are React Native and half of them are native directly. And then a handful of views are actually hybrid. There are bits of React Native and bits of direct native. And you probably can't tell which is which.
And then our main Facebook iOS and Android applications are just now experimenting with using React Native in some parts. Those apps are much more sensitive to newer technologies. They want to have things that are proven to be stable and performant first, which is why we started out with these other applications as testing grounds. But since those have gone well, I think we'll see a lot more teams at Facebook, hopefully outside of Facebook as well, start to use React Native in their apps.
CHUCK:
Awesome. We have a React Native show actually starting up on DevChat.tv.
LEE:
Cool. Yeah, it's super interesting technology.
JESSICA:
We had a [inaudible] ElixirConf a few weeks back. And in my talk I talked about what comes after REST? And I said it's GraphQL. But the interesting part was I was the third person to say that that day.
CHUCK:
[Chuckles] Awesome.
LEE:
Wow. That's so cool.
JESSICA:
Yeah. There's a lot of talk about GraphQL at ElixirConf. And there's great buzz around it, which is fantastic because I really do think it's the interface of the future.
LEE:
I hope so. You know, it's still just the beginning. We launched the spec as a preview draft three months ago and we had a reference implementation. And we've been iterating, improving, and adding things and taking feedback and adding things. So, I'm just so happy that there's buzz around this because it means that people are engaging with us and coming up with awesome ideas and really stress testing what we've built to make sure that it actually works for all the use cases they have. I expect that to continue over the next months, even years, as this thing improves. But yeah, I really hope that it becomes a major piece of the architecture of how we build modern applications.
JESSICA:
I think it will. You mentioned something about the types earlier that I found interesting, that they types seem to be there to protect the server, not the client, because you can always return null.
LEE:
Mmhmm.
JESSICA:
So, the clients have got to do their own checks. But there's one other player in here that the types really serve that when I saw your talk at React Rally I was really impressed with. They types also serve the developer. You mentioned in terms of generating code based on them and that's one way. But the other way was the interface that lets a client developer explore the API.
LEE:
Yeah. This is actually I think the most important part of having strong types. And we're not the first ones to do this of course. A lot of languages that have strong types will generate documentation from those types. But we've built GraphQL with first principles that things should be documented in code rather than parallel to the code. So, rather than having, I write my code here and then I write my documentation in this CMS over here, you write your documentation inline with writing your types. And that means that when you have that, it becomes just part of the metadata of your server. And so, you can generate a documentation browser. You can generate various kinds of useful tools.
One of the things that we've done that's been pretty cool is we use that metadata in our IDEs, our client IDEs for iOS and Android such that as you're typing out GraphQL queries inline with the rest of the programming that you're doing, we can show you the descriptions for the field that you're typing as you're typing it. So, we can do code intelligence. But that code intelligence is not coming from your codebase. It's coming from the server. So, there are all kinds of really cool stuff you can do when you just assume the documentation is part of the metadata foundation of the server that you're building.
And I should mention the tool that I'm sure you're referring to. It's GraphiQL, which is Graph I-Q-L. We pronounce it 'graphical'. And it's a tool that you can just stick… If you're server says that it implements GraphQL and it implements it with a single endpoint, then you can put this tool in front of it and it should just work. And it will give you an interactive IDE kind of experience in the browser where on one side of the screen you can type out queries and you get typeaheads. And you get live documentation. And then you hit enter and it runs the query and it shows you the result on the other side.
And it's just super useful for exploring what's possible in an API and gut-checking to make sure your queries work correctly before you then take those and paste them into your Relay application or your iOS or Android application. It's super useful. We've been using it at Facebook for years and we open sourced it a month and a half ago at React Rally, actually. It's where we relaunched it.
And it's the thing that once you see it you go, “Oh, that's how GraphQL works. I get it now,” which is hard to do [chuckles] just explaining something. So, totally useful. Check out GraphiQL.
CHUCK:
If people want to know more about GraphQL or GraphQL with Ruby, where do they go?
LEE:
They can go to GraphQL.org. So, GraphQL.org has links out to a bunch of the repositories that Facebook has put up. It has links out to a lot of the repositories that the community has been maintaining for the GraphQL implementations in various languages. We have a Slack channel that we've been using. Although we are closely running up to the maximum number of people that you can have in a Slack channel. So, hopefully we can find a successor for the Slack channel relatively soon.
CHUCK:
What's the limit on that? I didn't even know there was one.
LEE:
I think it's 10,000.
CHUCK:
Oh, wow.
LEE:
And we…
CORALINE:
The successor to that is IRC.
CHUCK:
[Chuckles]
LEE:
The successor and predecessor to Slack is IRC I think.
CORALINE:
Yes.
LEE:
Yeah, we were using IRC before and we liked that Slack does formatting of text in a way that everyone is guaranteed to get the same kind of result.
CHUCK:
Is there a limit on Gitter.im?
LEE:
I don't know. I haven't looked into that as much. I know the Reactiflux group which hosts Relay and React and React Native and a bunch of those channels all moved to Discourse, I believe. So, we may investigate that. But we still have plenty of time I think before we'll hit our upper limit on Slack. But certainly, if you're interested in asking more questions check us out on Slack. There are usually a lot of people hanging out in that general channel. And usually they'll get answers from the community long before someone from my team will get to you, which is exactly how it should be.
CHUCK:
Alright. Well, let's go ahead and do the picks. Before we get to the picks, we're going to give a quick mention to our silver sponsors.
[This episode is sponsored by Code School. Code School is an online learning destination for existing and aspiring developers that teaches through entertaining content. They provide immersive video lessons with inbrowser challenges which means that each course has a unique theme and storyline and feels much more like a game. Whether you've been programming for a long time or have only just begun, Code School has something for everyone. You can master Ruby on Rails or JavaScript as well as Git, HTML, CSS, and iOS. And more than a million people around the world use Code School to improve their development skills by learning or doing. You can find more information at CodeSchool.com/RubyRogues.]
CHUCK:
Jessica, do you want to start us with picks?
JESSICA:
Sure. This is my first week on Ruby Rogues as an employee of Stripe.
CHUCK:
Yay.
JESSICA:
So, I'm going to pick San Francisco, because it is such a lovely place to visit, especially when I don't have to pay for housing.
[Chuckles]
JESSICA:
And in particular, I want to pick Dolores Park where I happened to wind up on Sunday. And it was a sunny day and there's just this huge park where people sit in the grass on blankets or on the grass. And it's as if they were at a concert but there's no concert. They're just hanging out in the park. And it was really cool. So, that's my pick.
LEE:
I love Dolores Park.
CHUCK:
Alright. Well, Coraline, what are your picks?
CORALINE:
This is my first Ruby Rogues since leaving Instructure. I'm starting at Healthfinch. But my picks have nothing to do with that.
[Laughter]
CORALINE:
The first pick is a blog post by a guy named Greg Heo. It's called 'Outlining Your Conference Talk Pixar-style'. He talks about using a narrative to strengthen the structure of a talk. It's based on a piece of writing by Emma Coats who was a freelance director formerly at Pixar and describes a classic narrative structure of exposition, rising action, conflict and climax, and resolution. The idea is that information is nice and stories are fun. But the best talks inspire an audience to do something. So, thinking about the story behind your talk reminds you to keep your audiences' goals and your overall story in mind. And I'll link to that blog post in the show notes.
My second pick is a website called Walnut which is really a strange and neat kind of thing. It's a web-based algorithm visualizer. You have to sign up for an account in it. Once you sign up for an account, you can create your world defining a structure and the rules of the environment and the effect of the environment on agents' actions. You set a configuration of the world consisting of an initial state, which agents will interact, and what their goals are. Then you program the logic for agents following the rules of the world. And at the end you get a graphical display of what happened during your simulation. They have a bunch of examples. There's a library of examples you can explore, including a TCP connection, a state machine, a graphical demo of the 8 queens problem, and Langton's ant. So, it's pretty cool. It's TheWalnut.io. And it's something that you can lose yourself in for a few hours as you build worlds and build your own simulations. So, that's it for me.
CHUCK:
Alright. David, what are your picks?
DAVID:
Okay, I just have one pick today. And I'm going to try not to ramble too much because we don't have 40 minutes for me to do this. A lot of you who have been following me on Twitter know that I've been getting into leather work lately. I've been tooling, stamping, dying leather and making various projects with it. And I fell in love with this on accident back in May. I just, I saw a leather, simple leather project in a movie. It was a journal. And I thought, “I want one of those and I want to make it myself.” So, I walked into Tandy Leather factory and that's my first pick, is Tandy Leather factory. They're at TandyLeather.com. And they saw me coming. They really did. I could have walked out of there with just a swatch of leather and a concho, that's the little metal stud that sticks up that you can wrap a lace around. That's all I needed to make a journal. But the gal that I talked to down there convinced me to buy half a hide, like 24 square feet of leather. [Laughter]
DAVID:
And $100 worth of tools. And yeah, it's been five or six months. I've dumped over a thousand dollars on Tandy Leather at that store. They know me by name because, well I think they just call me the sucker when I'm not there. But… [Laughter]
DAVID:
I've really, really enjoyed getting into this hobby. I find it incredibly relaxing. I find it just soothing to just work with my hands. I'll go sit out in the front room. I've got a table set up as a workbench. Liz sits next to me. We stand up the laptop and we watch movies. And if you are interested in getting started with leather, I recommend TandyLeather.com. I also recommend you go out to YouTube and search for Ian Atkinson. His YouTube… I'll link to him in the show, but his YouTube username is satansbarber. And he runs Leodis Leather out of somewhere in England. He's got an amazing accent. It's not quite Scottish. But the word ‘layers’ is just one syllable. It's L-E-H-S. It's just, [speaking in accent] “This project can have many layers”. It's just a fantastic accent. And he's been working leather for several years. And if you go back to his old stuff he has beginner tools and he doesn't know what he's doing. And it's fun to watch him evolve and learn.
Bruce Cheaney is also a fantastic YouTube person to watch. He's an old guy who's been doing saddles his whole life. And he started doing training videos. And he's just a sweet guy that will just sit down and show you for beginners, these are the mistakes you're going to make and these are how you get really good results. And his leather work is just amazing. Once you get into that, you'll quickly realize that Tandy Leather is kind of the Walmart of leather supplies. A lot of their stuff is really good for the entry level person. But the more advanced stuff they don't often carry because it's too expensive for their price point. So, you're going to want some nicer quality leather and you're going to want some nicer tools. And you're also going to want a bunch of junk crap to practice on. So, I'm going to give you how to go up and down in quality. To go up, a great place is Springfield Leather. And they're in Springfield, Missouri I think. And they will ship you all the different kind of stuff that you need. And they have really good quality stuff. They have really great training videos and really nice staff.
So, I want to give them a big shout-out. If you want to get a bunch of leather to play with, go to TandyLeatherOutlet.com. That's where Tandy dumps all of their surplus stuff that they can't get rid of and you can buy remnants. Vegetable tanned leather is the stuff that you can tool on. They sell it in black, natural, and white. And the black stuff comes in belt, various width strips, and it comes in the round holster end cut-offs things that they cut off the bottom of hides. So, you can end up with decent sized pieces tool on and lots of belt strips to work on. The only problem with black is you can't dye black. It obviously doesn't work. But leather remnants tend to go for $5 a pound. So, it's like $50 for a 10 pound bag. And if you catch them on Tandy Leather Outlet you can get 10 pounds for $10. So, I have 75 pounds of scratch leather sitting around my house to play with and work with. So, a lot of fun. Fantastic hobby to get into. I highly recommend it. And good luck. Have fun.
CHUCK:
I'll go ahead and make a couple of picks here. The first one is I've been getting into a system called Ionic, Ionic Framework. It's based on Angular. It is hybrid apps. It's built on Cordova which is an Apache project. It used to be called PhoneGap. And it's been a lot of fun to dig into. And so, I'm going to pick that. And yeah, that's all I really got today.
I'm also posting stuff related to what I've got going on, on Periscope. So, if you want to check that out, all of that's at CharlesMaxWood.com.
Finally, Rails Remote Conf. I do want to talk about that for a minute. Initially there were going to be 12 sessions. There are now going to be 15 sessions. We added three sessions just because I had some awesome people come through and I couldn't say no to them. So, I said yes to them. And so, really excited about that. Jessica and Coraline are both speaking at that.
CORALINE:
Yay.
CHUCK:
And it's just going to be awesome. So, make sure you go to RailsRemoteConf.com and get your ticket. One other thing that you may want to keep an eye out for as this comes out is that I am going to be doing a remote conference every month next year. I had a lot of people asking for it and so I decided to go for it. They're about all kinds of things. Obviously I'm doing Ruby, Rails, JavaScript, Angular, and iOS, and freelancing since I have shows for those. I'm also doing Git, NoSQL, PostgreSQL, I think I'm doing PostgreSQL, podcasting, and a couple of others. So, that's going to be at AllRemoteConfs.com. It's not up as we record this but it will be up within a few weeks of getting this done. So, it should be out pretty close to when this comes out. So, if you're looking for opportunities to go and learn from folks who are up there and out there in the community, give great talks about topics you’re interested in without having to travel, then go check that out. But I am doing JS Remote Conf in January and the CFP for that is actually open right now.
DAVID:
Cool.
CHUCK:
And yeah, enough about my stuff. Lee, what are your picks?
LEE:
Let's see. I have two things to toss into the pile here. One is Flow type. Flow type is another Facebook project not by my team but one that our team loves to use, which adds a type system to JavaScript. So, all the love of type systems on top of our fun, dynamic JavaScript. It's helped find and fix tons and tons of problems in all of the open source software that we've been writing. And it will do similar magic for your stuff. So, definitely go check out Flow type. You can find that at FlowType.org, I believe.
And the other is a book called 'The Firesteel' which is a fiction novel and super fun. It's got a love story, time travel, and it's set in many different eras of history. Greek, Roman, modern day, and everything in between. And it's super fun. So, that book just came out last week and it's one of my favorites. So, check out 'The Firesteel'. And that's TheFiresteel.com.
CHUCK:
Alright. Well, thanks for coming, Lee. And thanks to all of our regular panelists for coming as well.
LEE:
Yeah.
CHUCK:
We'll go ahead and wrap this show up and we'll catch you all next week.
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit CacheFly.com to learn more.]
[Would you like to join a conversation with the Rogues and their guests? Want to support the show? We have a forum that allows you to join the conversation and support the show at the same time. You can sign up at RubyRogues.com/Parley.]