4 ms·
I don't think GraphQL is over-hyped at all. Maybe it's flawed, but the design is absolutely on the right traack. GraphQL completely changes how you work with AP
by atombender 8y ago
I don't think GraphQL is over-hyped at all. Maybe it's flawed, but the design is absolutely on the right traack. GraphQL completely changes how you work with APIs in a front end.
I work on React apps, and by using GraphQL, a component's data requirements can now be entirely declarative. For example, a component can do this (simplified):
<Query query=`{
posts(limit: 10) {
title, creator { name }
}
}`>
{({data, loading, error}) => {
return <ul>
{data.posts.map((title, {creator}) => <li>
{title} by {creator.name}
</li>)}
</ul>
}}
</Query>
The component knows what it needs to render, so it declares that. With TypeScript, you can get type-safety all the way from the backend to the frontend, which means your IDE (e.g. VS Code) can correctly autocomplete, say, "creator." and suggest "name". It's rather magical.
I work on a product called Sanity [1], which evolves GraphQL one step further. It's a Firebase-like data store with schemas and joins, and a structured data model. Without implementing anything on the server end, you can run queries like these:
*[_type == "post" && published] {
title,
creator -> { name },
topPosts: *[creator.id == ^.creator._ref] {
_id, title
} | order(viewCount desc)[0..10],
photos: photo -> {url}
} | order(_createdAt desc)[0..100]
This doesn't just follow a child object (creator), it also joins with an unrelated set of objects (topPosts, which finds the top 10 most viewed posts created by the same user) as well as joining a bunch of 1:1 relations. I'm totally biased, but I think it's a game-changer when it comes to writing web apps, because you can just dump the whole query in a React component, no state management or API writing required.
[1] https://www.sanity.io/ https://www.sanity.io/
- hardwaresofton 8y agoNothing about what you just posted couldn't be done with a normal RESTful endpoint with sufficient support for column-level filtering and embedded item filtering. Your post is the perfect example of GraphQL is being over hyped. I absolutely get that there's a benefit to filtering at both these levels, and that the DSL cuts down on noise and gives you a way to "query" without thinking of web requests, but it's not a leap in thinking -- teams that have to deal with mobile environments have long been strapping on filtering options to endpoints to avoid sending unneeded bytes to mobile devices. Yes -- GraphQL standardizes this stuff, but it does it in a way that is basically not compatible with anything else. > The component knows what it needs to render, so it declares that. ??? The component doesn't know anything, components don't think. You're describing it as if you just gave the component a list of entities but you actually wrote a query DSL -- that's how the component "knows" -- you told it. What GraphQL is doing for you here is: - Enforcing consistent access patterns (which is how "posts" gets translated into the right URL) - Ensuring "limit" is supported on the endpoint - Ensuring horizontal filtering is supported - Ensuring embedded entities get returned and they're filtered This is not a paradigm shift. It's better, maybe, but that DSL will absolutely fail you at some point, when you try do a more dynamic query, and you'll have to drop back to writing code that looks a lot like life did before GraphQL. > With TypeScript, you can get type-safety all the way from the backend to the frontend, which means your IDE (e.g. VS Code) can correctly autocomplete, say, "creator." and suggest "name". It's rather magical. This is basically orthogonal... Write well typed javascript and your IDE is going to be able to help you out. > Firebase-like data store with schemas and joins You've lost me here. The excerpt you've posted looks even worse than SQL. At that point why not just send SQL directly to the backend (as long as you can get the permissions right and your DB is secure enough)?
- atombender 8y agoCould one invent an ad-hoc REST API to perform joins, apply parameters and so forth? Of course. That's what people have been doing. That means every solution is ad-hoc. People get tired of this. Have you tried any of the GraphQL client tools? You can literally point a client at an arbitrary server and not only see its schema, but also interact with the API. REST doesn't give you that, because the authors of REST neglected to actually specify anything beyond some fuzzy principles. > ??? The component doesn't know anything, components don't think. This is being obtuse. You know perfectly well what I meant: That the component localizes the information needed to make an informed request. This is domain knowledge encoded in the component. This is contrary to how most developers design clients, where they might call an endpoint such as /posts?limit=10, which happens to fetch all attributes, even if the component doesn't actually need all the attributes. > You've lost me here. The excerpt you've posted looks even worse than SQL. Before a summary (and, honestly, tone deaf) dismissal such as this, I recommend reading up on it a bit [1], and maybe trying it out. SQL is great, but it does not handle nested documents/relationships, so you end up with a lot of messy structural mapping between flat relational data and structured data, which is why projects like Rails/ActiveRecord and Hibernate are so popular. For example, a query such as this: *{ name, photos->{ url }, friends->{ name } } will return something like: [ { "name": "Bob", "photos": [ {"url": "http://..."}, {"url": "http://..."} ], "friends": [ {"name": "Jane"} ] }, ... ] The point isn't that you cannot, with a sufficiently complex ORM and enough elbow grease, do that with SQL. It's that it should be unnecessary, because developers shouldn't need to write an entire data layer every time they want to bring an app up. This is part of what GraphQL brings to the table, too. [1] https://www.sanity.io/docs/data-store/how-queries-work https://www.sanity.io/docs/data-store/how-queries-work
- hardwaresofton 8y agoGraphQL certainly has a cleaner/less involved interface, but it's also less interoperable. My problem with it is that it doesn't offer much value for the amount of effort, and it isn't the paradigm shift it's claiming to be in the first place, it's just being marketed well. HateOAS[0]+Swagger[1]/jsonschema hyperschema[2] is enough to do what GraphQL does. > This is being obtuse. You know perfectly well what I meant: That the component localizes the information needed to make an informed request. This is domain knowledge encoded in the component. > This is contrary to how most developers design clients, where they might call an endpoint such as /posts?limit=10, which happens to fetch all attributes, even if the component doesn't actually need all the attributes. I apologize, that was a terrible way to phrase my objection. But I want to note that basically GraphQL has offered you a way to avoid writing: axios.get("/posts?limit=10&filter[0]=prop&filter[1]=otherProp&fetchEmbeddedEntities[0]=thing") My point was that you can tack on a not-string query API that declaratively builds this without committing to "implementing a GraphQL endpoint" for all your APIs -- the technology is already there, what people are lacking is shared structure. GraphQL does create shared structure, but in an all-or-nothing way and I avoid building with tools that do that. BTW, as far as actual dynamic API recognition goes, the promise of jsonschema + json hyperschema + json LD is much more promising (it's basically equivalent to the semantic web promise) -- GraphQL is a step in the right direction but the lack of interop means we have to step backwards to go in any other direction. Let me put it this way, could you imagine writing a query where you don't know the name of the model on the server side? Like you only know the thing you want (let's say a "vehicle"), and you know the backend has "vehicles" but you don't know what they're called? Being able to do that query is a paradigm shift, and it's possible with the tools I mentioned, though the promise is yet to be realized by and large. > Before a summary (and, honestly, tone deaf) dismissal such as this, I recommend reading up on it a bit [1], and maybe trying it out. SQL is great, but it does not handle nested documents/relationships, so you end up with a lot of messy structural mapping between flat relational data and structured data, which is why projects like Rails/ActiveRecord and Hibernate are so popular. I've tried it -- I'm not impressed, this is the crux of my point and I haven't seen anything yet that can help me change my mind. It is a fact that the chunk of code you posted as a query is a nightmare to look at. Yes, my brain will eventually Despite how people try there aren't many query languages that can match the expressive power of SQL. For all it's warts, it is excellent at what it does. > SQL is great, but it does not handle nested documents/relationships, so you end up with a lot of messy structural mapping between flat relational data and structured data, which is why projects like Rails/ActiveRecord and Hibernate are so popular. This is a wildly inaccurate statement. SQL is for querying relational database systems. Well structured relational data is the most structured data you're ever going to find. ORMs (ActiveRecord/Hibernate) are: - excellent at reducing boilerplate when it's a perfect fit (pro) - often used by people who don't understand the expressive SQL (con) - great at creating N+1 query problems (con) - great at stopping you from using the deeper features of your DB (con) ORMs are easier, that's why they saw widespread use. It's been my experience that people fall out of love with ORMs as they reach their rough edges (which they must have, they are leaky abstractions). I much prefer query builders/generators and in-language level abstractions (methods/functions/etc). > For example, a query such as this: Please stop posting queries, I get the query language, the DSL is fairly easy to understand (this is great for GraphQL). > The point isn't that you cannot, with a sufficiently complex ORM and enough elbow grease, do that with SQL. It's that it should be unnecessary, because developers shouldn't need to write an entire data layer every time they want to bring an app up. This is part of what GraphQL brings to the table, too. I think you've conflated an ORM with a sufficiently capable and metadata-tagged backend. These features aren't ORM level feature necessarily, look at Postgrest's vertical column filtering[3] and embedded entities[4]. Also, my original point was that GraphQL is over-hyped considering that it is not a paradigm shift, and requires you to do a bunch of non-interoperable work aside from REST without much benefit. I'm going to find some time and implement GraphQL automatically (with the help of jsonschema and hyperschema, etc) on top of a regular RESTful endpoint, I'll post it to HN when I do. [0]: https://en.wikipedia.org/wiki/HATEOAS https://en.wikipedia.org/wiki/HATEOAS [1]: https://swagger.io/specification/ https://swagger.io/specification/ [2]: https://datatracker.ietf.org/doc/draft-handrews-json-schema-hyperschema/ https://datatracker.ietf.org/doc/draft-handrews-json-schema-... [3]: https://postgrest.org/en/v5.1/api.html#vertical-filtering-columns https://postgrest.org/en/v5.1/api.html#vertical-filtering-co... [4]: https://postgrest.org/en/v5.1/api.html#resource-embedding https://postgrest.org/en/v5.1/api.html#resource-embedding