[HN Gopher] SwiftGraphQL - A GraphQL client that lets you forget...
       ___________________________________________________________________
        
       SwiftGraphQL - A GraphQL client that lets you forget about GraphQL
        
       Author : maticzav
       Score  : 91 points
       Date   : 2021-02-22 13:07 UTC (9 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | Kaze404 wrote:
       | I love code generation from GraphQL. Elm-graphql is a great
       | example of this and works incredibly well, to the point where it
       | sold me on GraphQL entirely.
        
         | maticzav wrote:
         | SwiftGraphQL was actually inspired by Elm GraphQL! Dillon - the
         | creator of Elm GraphQL - even helped me understand a couple of
         | concepts he used in that library that we also use in
         | SwiftGraphQL.
        
       | dsabanin wrote:
       | What's with the GraphQL luddism on HN? I'm as much opposed to
       | adding more incidental complexity to the frontend as the next
       | guy, but GraphQL has objective purpose and makes a lot of things
       | much simpler than they would be without it.
       | 
       | Learning new things and doing things better than they were done a
       | year before is an essential part of being a professional software
       | engineer, it's what makes this field hard and that's why we're
       | paid so much. It's what makes us able to tackle so much added
       | complexity of the world, new use cases, new platforms and
       | paradigm shifts over the years. To me, it's also what makes it so
       | challenging and rewarding.
        
         | ritchiea wrote:
         | It's dismissive to call it luddism. I am a big anti-GraphQL
         | voice but in the specific cases where I tend to work: on small
         | cross functional, often full stack dev teams. It's a layer of
         | formal promises about the API that I find extremely unnecessary
         | & unproductive for small teams that I can see the appeal for at
         | a huge corp like Facebook where frontend devs probably don't
         | write much or any backend code.
         | 
         | The problem usually isn't the library itself and that's true of
         | GraohQL. It's the cargo culting of GraphQL & other new tech
         | that might be unnecessary or overengineering for your specific
         | use case.
        
       | adsharma wrote:
       | Re: Conways law at Facebook
       | 
       | I was at Facebook when GraphQL was invented, maintaining a
       | backend storage service where a core assumption was that storage
       | should be reorganized based on access patterns and that
       | predicates should be pushed down to storage where they can be
       | executed more efficiently.
       | 
       | GraphQL was hard to push predicates down, because you don't know
       | which of the edges were written in PHP.
       | 
       | My response was fquery[1], which is like what's being discussed
       | here but with python as the source language instead of swift and
       | amenable to preserving the largest possible query structure for
       | backend optimizers, including SQL optimizers.
       | 
       | It has some early demos converting a GraphQL/fquery into SQL
       | where possible. It should be possible to add enough metadata to
       | fquery to identify if an edge is non-trivial (calls into another
       | microservice) or trivial (can be optimized to a storage backend
       | or SQL).
       | 
       | [1] https://github.com/adsharma/fquery
        
       | msoad wrote:
       | Wouldn't it be better to generate those structs from API schema?
        
         | yeneek wrote:
         | I have the same opinion. The big problem I had with generating
         | graphql api from code, was that the result graphql schema was
         | badly done. It's hard to design API that way. I made similar
         | module for typescript just to realize, that I don't want to
         | build graphql endpoints this way.
         | 
         | that module: https://github.com/captain-refactor/graphql-
         | compose-typescri...
        
         | harryf wrote:
         | You mean something like https://github.com/banjun/WSDL2Swift ?
        
         | maticzav wrote:
         | SwiftGraphQL also generates API structs from the schema.
         | 
         | Maybe you are referring to generating the model from the
         | queries. The problem we had with that approach was that it's
         | hard to reuse the generated structures in your application
         | model. You can read more about the idea here:
         | 
         | https://github.com/maticzav/swift-graphql#what-are-the-pitfa...
        
       | [deleted]
        
       | kva wrote:
       | I <3 GQL but this just sounds like "Forget the GraphQL DSL to
       | learn our DSL"
        
       | mjmahone17 wrote:
       | This is really cool! I love seeing GraphQL back in its roots as a
       | way of improving the developer experience for native iOS apps.
       | 
       | From what I understand, this project tries to solve one clear
       | pain point that isn't solved elsewhere: Swift developers can use
       | GraphQL in Swift without writing GraphQL directly. Being able to
       | create idiomatic operations through Swift is nifty to see.
       | 
       | Somewhat interestingly, it seems like to solve other problems,
       | @maticzav is independently following similar paths that the
       | original developers of GraphQL in Objective-C followed. Some of
       | the highlights:
       | 
       | - Using code generation to make access patterns more type safe.
       | 
       | - Creating a centralized set of Type Models, that map 1:1 with
       | the schema the app accesses.
       | 
       | - Mostly separating the GraphQL operations (in this case, as
       | written in Swift) from the models a component interacts with: the
       | components just see that they have a Schema-based Type Model.
       | 
       | I'd personally think about using the query-creation API to
       | produce query (and fragment, once those are supported) specific
       | models for consumption. The problems of both over and under
       | fetching may expose themselves when more than a couple
       | interactions are operating with different views over the same
       | types. I've talked about why Facebook no longer recommends Type
       | Models before: https://www.youtube.com/watch?v=Vo8nqjiKI3A
       | 
       | It's really encouraging to see the recent explosion of ideas for
       | "how to do GraphQL": I'm not sure what sort of synthesis these
       | myriad projects will create for the broader community.
        
       | jtdev wrote:
       | Can we just forget about GraphQL completely instead?
        
         | runawaybottle wrote:
         | Oh come on! My company just forced me to learn it for a better
         | part of a year. We can't be done with it, it's not fair.
         | 
         | I was told this was the new hotness, and I can't be lied to.
         | Plus, many job descriptions were asking for Graphql about 2
         | years ago, so what gives? Is life not fair? I was told it was
         | fair this time around.
        
         | blacktriangle wrote:
         | I have, but I also don't work in an organization that has
         | separate and large front-end and back-end teams. GraphQL looks
         | less like an objectively useful technology and more of a
         | realization of Conway's Law in response to Facebook's
         | organization.
        
           | RyanShook wrote:
           | Great point. GraphQL looks like overkill for small projects
           | but at the right size it probably makes perfect sense.
        
             | arcturus17 wrote:
             | "Conway's law is an adage stating that organizations design
             | systems which mirror their own communication structure"
             | 
             | So if GP is correct and we take them literally then you
             | shouldn't only have the right size, but also a structure
             | that's close to Facebook's...
        
           | jaegerpicker wrote:
           | As a Mobile Dev/Frontend Dev GraphQL is a massive win to work
           | with. No more requesting/building end points to satisfy the
           | screen you are building. Adding fields is non-destructive.
           | Controlling the shape of the data returned (to an extent, you
           | still have to return it in the nested layers the schema is
           | designed towards). I know a ton of backend or full stack devs
           | that don't think that GraphQL is worth it but very FEW UI
           | devs that agree. It's really nice to build UI's against. I've
           | tried SOAP, REST, HATEOAS, Swagger/OpenAPI, and protobuffers.
           | Protobuffers are the only one with as good a developer
           | experience IMO. GraphQL is OBJECTIVELY useful it might not be
           | useful to you apps though and that's ok.
        
             | blacktriangle wrote:
             | Objectively was probably the wrong word, maybe "generally"
             | would be more accurate. I was looking to contrast GraphQL
             | with something like REST which is an incredibly powerful
             | generic mental model, where GraphQL seems more specifically
             | tuned to solve front end developer's issues.
        
       | j_m_b wrote:
       | I wondered when the GraphQL "ORMs" would start appearing!
        
       | andrewingram wrote:
       | There's also:
       | 
       | - Relay-swift: A port of Relay to Swift - https://relay-
       | tools.github.io/Relay.swift/docs/
       | 
       | - Graphaello: Inspired by Relay, but deviates a bit more from the
       | patterns than Relay-swift -
       | https://github.com/nerdsupremacist/Graphaello
        
         | maticzav wrote:
         | Thank you for adding the links!
         | 
         | The main difference between these clients and SwiftGraphQL is
         | that SwiftGraphQL tries to abstract away GraphQL in favour of
         | Swift language feature.
         | 
         | `relay-swift`, for example, relies on query strings which
         | doesn't bring type-safety to your code;
         | 
         | `graphaello` is indeed very similar and I've tried using it
         | before creating SwiftGraphQL. One of the goals of SwiftGraphQL
         | was to let you easily separate the model from your queries.
         | That's why we let you do complex logic in the selection itself.
         | Otherwise, you'd have to first create a utility struct and then
         | translate it into a model-type. I think that's the main
         | difference between graphaello and SwiftGraphQL
         | 
         | Thanks again for sharing the links!
        
           | ericlewis wrote:
           | Relay.swift doesn't bring type-safety to your _queries_ but
           | it does use the relay-compiler which will fail if anything is
           | wrong (at least helpful!) and you still get type safety for
           | _results_ as well as automatic conformance to Identifiable  &
           | custom scalar type substitutions.
           | 
           | Haven't checked out SwiftGraphQL much, but Relay.swift is
           | definitely the best swift based GQL I have used to date.
        
       | pcr910303 wrote:
       | So a bunch of people on HN are now arguing that GraphQL should
       | disappear?
       | 
       | GraphQL is a genuinely objectively useful technology in places
       | that have a frontend-backend split (including non-web frontends).
       | It doesn't require building specific APIs for specific pages for
       | speed concerns. It allows backends to add fields non-
       | destructively (RESTful JSON does work at the cost of a bigger
       | network payload).
       | 
       | GraphQL provides the right tools for the right problem, and has
       | created an ecosystem around it. (How should I reliably compute a
       | SQL query cost? How should I control data access policy in SQL?
       | How should I return the SQL result in a easily-parsable format?)
        
       | santialbo wrote:
       | I see a lot of hatred in the comments towards GraphQL. Is someone
       | forcing you to use it against your will?
       | 
       | I've been using it for more than a year with TypeScript types
       | generation and couldn't be happier. All of my interactions with
       | the server are properly typed and haven't had a single bug
       | related to server/client missmatches.
        
         | tylerchilds wrote:
         | > Is someone forcing you to use it against your will?
         | 
         | I mean, kind of?
         | 
         | My problem with GraphQL isn't necessarily GraphQL itself, but
         | with the sprawl of things creeping further and further into
         | client-side code.
         | 
         | As companies are finding GraphQL to "unlock greater developer
         | productivity", it's becoming more and more expected to have
         | this in our toolkit as "front-end people".
         | 
         | There's been a few blog posts recently that I relate to. I feel
         | like I'm at a point in my career where I could "knuckle-down
         | and get good" but I don't actually want to get good at more and
         | more endless technologies. I'd rather be able to define my
         | niche specialization and thrive within that space.
         | 
         | [1]: https://bradfrost.com/blog/post/front-of-the-front-end-
         | and-b...
         | 
         | [2]: https://www.trysmudford.com/blog/i-think-im-a-design-
         | enginee...
         | 
         | [3]: https://notes.baldurbjarnason.com/2021/02/20/the-layers-
         | of.h...
        
         | serverholic wrote:
         | There are a bunch of elitists on here who get off on hating
         | popular things.
         | 
         | I find it amusing that some of the comments are basically "Why
         | use graphql when I can combine these 5 other technologies to do
         | the same thing?"
        
         | [deleted]
        
       | hardwaresofton wrote:
       | Another week, another submission that hopefully edges more people
       | towards realizing that they've just created an under-
       | standardized, under-powered SQL-with-braackets that forces you to
       | bring your own query optimizer, and eschews the advancements of
       | Swagger/OpenAPI, JSONSchema, HAL, JSON-LD and the flexibility of
       | HATEOAS.
       | 
       | All for a little bit of a velocity gain from declarative syntax
       | and horizontal/vertical filtering.
       | 
       | This code is probably very useful to the people who made it and
       | those in the GraphQL+Swift ecosystem, but we were already here
       | (and just starting to get drastically better) with OpenAPI --
       | it's not like all the effort is only going in one direction but
       | GraphQL really feels like a less-than-optimal branch.
       | 
       | The final piece of the puzzle for me will be when someone starts
       | to replace the dynamic properties of the more advanced REST-ful
       | techniques (API discovery, link following, etc) in GraphQL. Then
       | the circle will be complete -- we'll have rebuilt XML (in the
       | "linked data" respect anyway, not so much the accidental
       | complexity side) and it's related standards twice in under ~20
       | years.
        
         | jkcxn wrote:
         | > replace the dynamic properties of the more advanced REST-ful
         | techniques (API discovery, link following, etc) in GraphQL
         | 
         | Isn't this exactly what GraphQL does? I may be missing
         | something
        
         | mikecaulley wrote:
         | I've found GraphQL to greatly improve the developer experience
         | when building web apps. As a front-end developer you can easily
         | get a full view of the data and relationships. Tools like
         | GraphiQL make exploring APIs a pleasure. And regardless of what
         | you need to present to the user on screen, you can quickly
         | build a request that perfectly matches the data you need. There
         | is also the nice addition of strict typing and there are
         | libraries that automatically generate TypeScript types for you
         | from the schema and/or your operations.
        
           | criddell wrote:
           | To what extent are you just pushing complexity to the back-
           | end developers?
           | 
           | > Tools like GraphiQL make exploring APIs a pleasure.
           | 
           | No argument there. Is there something similar for traditional
           | REST? For some reason, I thought the point of HATEOS was to
           | make that kind of exploration possible.
        
             | hardwaresofton wrote:
             | GraphQL cannot ever be explored in the same way HATEOAS can
             | because it is missing the linking part (and other related
             | technology like JSON-LD). That said, GraphQL _does_ offer
             | introspection[0] which is not a bad start but lacks the
             | breadth an depth of the hyperlink based approaches.
             | 
             | [0]: https://graphql.org/learn/introspection/
        
               | shoelessone wrote:
               | I 100% agree with your statement. I also realize you are
               | not championing HATEOAS here necessarily.
               | 
               | That said, I am curious if you have found this "linking"
               | aspect of HATEOAS useful for actual implementations? I
               | have been doing integration work with a system that
               | strictly adheres to "REST level 3" and "HATEOAS"
               | principles for the past few years, and I myself have
               | found the "explore-ability" of the API super handy. That
               | said, the self-documenting nature only goes so far, and
               | in the end I'm not sure the internal linking stuff is
               | preferable to robust documentation.
               | 
               | I'm not trying to be down on this necessarily, I actually
               | generally push back on the adoption of GraphQL as the
               | answer to every problem.
        
               | hardwaresofton wrote:
               | > That said, I am curious if you have found this
               | "linking" aspect of HATEOAS useful for actual
               | implementations? I have been doing integration work with
               | a system that strictly adheres to "REST level 3" and
               | "HATEOAS" principles for the past few years, and I myself
               | have found the "exploitability" of the API super handy.
               | That said, the self-documenting nature only goes so far,
               | and in the end I'm not sure the internal linking stuff is
               | preferable to robust documentation.
               | 
               | You're right, this is a reasonable question and the
               | answer is uncomfortable. I personally find it useful when
               | paired with OpenAPI -- generally by using annotations on
               | controllers and models, but it is indeed rare to have
               | usecases that fit the linking functionality well enough
               | to be significantly better than what you would get from
               | just good documentation.
               | 
               | The "killer app" of this space for me personally is a
               | Django Admin[0][1] (or React-Admin[2]) clone that is 100%
               | client-side automated. I don't have a demo yet, but once
               | I do it'll be up on HN.
               | 
               | > I'm not trying to be down on this necessarily, I
               | actually generally push back on the adoption of GraphQL
               | as the answer to every problem.
               | 
               | Please, feel free to push back, that's what discussion is
               | for, and ideas that can't stand up to push back probably
               | shouldn't be adopted.
               | 
               | [0]:
               | https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#
               | 
               | [1]: https://djangobook.com/mdj2-django-admin/
               | 
               | [2]: https://github.com/marmelab/react-admin
        
           | jamil7 wrote:
           | I don't have especially strong feelings either way, but the
           | majority of this is possible with OpenAPI as well.
        
           | kristaps wrote:
           | I would like a backend developer perspective on the same.
           | 
           | I haven't done any GraphQL stuff myself, but the "I can get
           | whatever data I need" aspect feels like a huge potential
           | headache for backend devs. Won't be a problem at prototype
           | scale, but once you have a significant client count, how do
           | you deal with unpredictable data access patterns that can't
           | be optimized ahead of time?
        
             | mikecaulley wrote:
             | Generally speaking, it's not more difficult than creating a
             | REST API controller. Rather than mapping your service code
             | to a controller, you map it to a (GraphQL) resolver. It
             | feels extremely similar.
             | 
             | There are different things to look out for; like handling
             | n+1 (https://shopify.engineering/solving-the-n-1-problem-
             | for-grap...) queries, but nothing that I can say is too
             | difficult.
        
               | dmitriid wrote:
               | It is more difficult. With REST you know ahead of time
               | which data you need, and you can optimise it as much as
               | you can. With GraphQL at any given point in time you have
               | no idea what the request is. Dataloaders solve it to some
               | extent, but not much.
        
               | mikecaulley wrote:
               | Of course, you are building something that is much more
               | powerful. If you intend every possible GraphQL operation
               | to perform perfectly, it'll take more development effort.
               | Though if you optimize for only the most likely cases,
               | the effort is not much greater.
        
               | dmitriid wrote:
               | > Though if you optimize for only the most likely cases,
               | the effort is not much greater.
               | 
               | That's why most discussions involving complexities of
               | GraphQL inevitably devolve into: "in production we only
               | allow a subset of queries". Because _actually_
               | implementing GraphQL as it 's specified and marketed is
               | quite an undertaking.
        
             | no_wizard wrote:
             | Inevitably you _do_ get a map of your data flow. GraphQL
             | can be a huge help here, because you must have resolvers
             | for the queries. It forces you to think ahead of time about
             | how you 're going to resolve getting the data to fulfill
             | the API "contract" if you will. You can optimize that.
             | GraphQL is great for describing your APIs in a type
             | safe(ish) way where you get great decoupling by design.
             | 
             | I also will say that since a query can use multiple
             | resolvers, that's where I have found it really shines. The
             | model does implicitly work best when you have async systems
             | over synchronous ones for more complex queries
             | (multithreaded/multiprocess)
             | 
             | that's my anecdote, as someone who is currently and
             | actively building and maintaining GraphQL backend services.
             | 
             | Its true you can get the same with any API design pattern,
             | really, I will say, however GraphQL has specifications for
             | all this, and I think that's what makes it more powerful
             | 
             | Another nice thing, is no versioning. I can just use the
             | `@deprecated` built in directive, and when the usage of a
             | deprecated part of an API gets consistently (for a
             | specified period of time) down to 0, I can just remove it
             | entirely.
             | 
             | OpenAPI and the like don't have a descriptive way to notify
             | users of an API of this, you, for better or worse, have to
             | version your API, which often ends up in situations where
             | you always have an old version sticking around for a very
             | long time.
             | 
             | Like all technologies though, it can (and does) have its
             | issues. It adds a certain amount of complexity to your
             | applications (more so for the client, IMO, even though
             | exploring APIs is a huge upside with tools like GraphiQL)
        
           | hardwaresofton wrote:
           | I do agree that GraphQL has improved developer experience, or
           | at the very least improved the perceived experience (which is
           | essentially the same as actually improving the experience). I
           | cannot deny it's popularity, and that comes from hype along
           | with usefulness (perceived or actual).
           | 
           | > Tools like GraphiQL make exploring APIs a pleasure.
           | 
           | This is an innovation of the developers of GraphiQL, _not_ of
           | GraphQL itself. It 's possible to build IDE support similar
           | ot that of GraphiQL, with the rich metadata and schema data
           | that is available by design in OpenAPI + JSONSchema + JSON-LD
           | + HATEOAS land. The problem is that no one did/was excited
           | enough to, the slog from Swagger2 to OpenAPI3 might have
           | sapped the enthusiasm of the community just enough (or the
           | emergence of GraphQL), but it's not that the tools isn't
           | possible with other approaches.
           | 
           | > There is also the nice addition of strict typing and there
           | are libraries that automatically generate TypeScript types
           | for you from the schema and/or your operations.
           | 
           | This was already present with OpenAPI and related tools, so I
           | personally don't put this as something that GraphQL brought
           | about.
        
             | serverholic wrote:
             | I don't want to piece together 4 different technologies to
             | get the same thing.
             | 
             | And it's not even the same thing. You keep mentioning
             | HATEOAS but that doesn't accomplish the same things as
             | graphql at all. With HATEOAS I need to send out multiple
             | requests to collect the data I need. With graphql I can
             | send out one request to retrieve exactly the data I need. I
             | can also combine multiple requests into a single request.
             | GraphQL also only retrieves the fields you need by default.
             | This is something you'd need to build manually with REST.
             | 
             | And yes, reducing the number of server requests does matter
             | when you're trying to optimize for the largest market
             | possible. Including people on slow mobile network
             | connections where every request adds significant overhead.
        
               | htormey wrote:
               | Also it can potentially reduce the client side logic
               | needed to stitch said 4 requests together.
               | 
               | This can be a big complexity/bug preventer for multi
               | client Apps (web, mobile, desktop).
        
               | hardwaresofton wrote:
               | > I don't want to piece together 4 different technologies
               | to get the same thing.
               | 
               | > And it's not even the same thing. You keep mentioning
               | HATEOAS but that doesn't accomplish the same things as
               | graphql at all. With HATEOAS I need to send out multiple
               | requests to collect the data I need. With graphql I can
               | send out one request to retrieve exactly the data I need.
               | I can also combine multiple requests into a single
               | request. GraphQL also only retrieves the fields you need
               | by default. This is something you'd need to build
               | manually with REST.
               | 
               | All of this is reasonable, but my point was that we've
               | abandoned a more flexible method, that had composable
               | functionality and agreed-upon standards for GraphQL. You
               | gained some pipelining, and some vertical filtering, but
               | threw out a lot with the bathwater.
               | 
               | GraphQL does give you a way to do these things, and this
               | is why it is popular (or at least a good reason why), but
               | it is missing the wider possibilities of the other
               | ecosystem. As people start to try and abstract over it
               | they will be abstracting over a less robust, considered,
               | standardized base.
               | 
               | > And yes, reducing the number of server requests does
               | matter when you're trying to optimize for the largest
               | market possible. Including people on slow mobile network
               | connections where every request adds significant
               | overhead.
               | 
               | Reducing the number of server requests does indeed matter
               | -- I did not mean to propose it doesn't, reducing request
               | was somewhat solved before now with the backend-for-
               | frontend approach. There are lots of approaches to help
               | people on slow mobile network connections, but the
               | ultimate one is to server-render and trim as much as
               | possible -- I'm not sure GraphQL is much better at this
               | than REST with efficient endpoint choice.
        
               | serverholic wrote:
               | > You gained some pipelining, and some vertical
               | filtering, but threw out a lot with the bathwater.
               | 
               | What are we missing that actually matters in practice?
               | And yes, if you minimize the problems that graphql was
               | built to solve it seems like a worse solution.
               | 
               | > As people start to try and abstract over it they will
               | be abstracting over a less robust, considered,
               | standardized base.
               | 
               | Facebook, a company who's apps serve billions of people
               | came up with graphql to solve real problems. Saying it
               | isn't well considered is asinine. As for standardization,
               | last time I checked GraphQL has a spec and the GraphQL
               | Foundation is a member of the Linux Foundation.
               | 
               | Again, what problems are you talking about that graphql
               | doesn't solve? I mean actual, practical problems.
               | 
               | > reducing request was somewhat solved before now with
               | the backend-for-frontend approach.
               | 
               | So now I need to write a backend for each use-case. That
               | sounds better. Or I need to make my endpoints extra
               | configurable which starts to approach graphql territory.
               | 
               | > the ultimate one is to server-render and trim as much
               | as possible
               | 
               | Again, we're now entering the "why graphql was invented"
               | territory. Sure I could add these to my REST endpoints..
               | OR I could write one graphql endpoint and get all of
               | these.
        
         | Lx1oG-AWb6h_ZG0 wrote:
         | The main advantage I've found with GraphQL is the normalized
         | cache in client libraries like Apollo or Relay. It allows
         | components to just ask for the data and not worry about how
         | it's fetched/stored/updated. The secondary benefit is that
         | _some_ (not all) of the data plumbing can be moved from the
         | frontend code to the backend, which makes for faster apps.
         | Beyond that, GraphQL is more of a hinderance than a help... its
         | type system in particular is brain dead and easily the worst
         | part of the entire experience (seriously, why _is_ there a
         | difference between inputs and types? Why can't you define input
         | unions, or maps, or recursive structures?)
         | 
         | Is there any equivalent for the latter with swagger? Yes, you
         | can do everything in there with custom redux middlewares or
         | sagas/observables, but it's more glue code you have to write
         | and maintain.
        
           | hardwaresofton wrote:
           | > The main advantage I've found with GraphQL is the
           | normalized cache in client libraries like Apollo or Relay. It
           | allows components to just ask for the data and not worry
           | about how it's fetched/stored/updated. The secondary benefit
           | is that _some_ (not all) of the data plumbing can be moved
           | from the frontend code to the backend, which makes for faster
           | apps.
           | 
           | Is this something you couldn't achieve with the idiomatic
           | rules on HTTP request types, and serialization of HTTP
           | requests parameters? It really depends on where you're trying
           | to do the caching and what kind of caching you're trying to
           | do.
           | 
           | A lot of work has gone into HTTP headers, method semantics,
           | and other details in order to facilitate caching. The
           | "backend for frontend" pattern has been very popular as of
           | late in order to try and shift the plumbing load, exposing
           | endpoints that are catered to certain clients to boost
           | efficiency -- would that be good enough for a corollary in
           | OpenAPI land?
        
             | lilactown wrote:
             | If you do a survey of front end data fetching frameworks,
             | they basically land in two categories:
             | 
             | - API-agnostic: react-query, rtk-query, swr
             | 
             | - Declarative queries (e.g. GraphQL): apollo-client, relay,
             | urql
             | 
             | A major difference to notice is that the API-agnostic
             | libraries do not handle normalizing the data before caching
             | it. Instead, they cache the data based on some key related
             | to the request. So you can potentially fetch and cache two
             | different versions of the (semantically) same information,
             | leading to UI incoherence. The various API-agnostic
             | libraries have ways of solving this by explicitly creating
             | relationships between different requests so that you can
             | manually say, "when I fetch with this key, also trigger a
             | re-fetch of any components subscribed to these other cache
             | keys." This is coarse, but for many cases "good enough" in
             | contexts where you don't have full control over the API you
             | are fetching data from.
             | 
             | In order to leverage a normalized cache, the layer between
             | the cache and network needs to intimately understand what
             | data is returned by which request so that it can support
             | things like stale-while-revalidating, re-rendering on
             | refetch of the same data from another part of the page,
             | etc. Describing all of the data that could possibly be
             | returned by an endpoint is tedious and error prone, as APIs
             | can be dynamic in what they return and backend changes
             | could easily lead to breaking any assumptions the frontend
             | might make about an opaque endpoint.
             | 
             | Now if you have more control over how a backend behaves and
             | buy-in on solving this problem full stack, you can start to
             | build some of these assumptions into both layers. For
             | instance, you could require all endpoints to be fully
             | documented via swagger, and the front end could use the
             | swagger JSON doc to map endpoints to data potentially
             | returned by a response. You would also need a pattern to
             | key each request with what entity (type + ID) it is
             | responding data with before it completes; HATEOAS provides
             | a standard of relating URIs to entities and would solve
             | this problem.
             | 
             | So you can see that this normalized caching problem can be
             | solved without GraphQL, as long as the backend and frontend
             | can agree on a set of standards and requirements such as
             | REST + HATEOAS + Swagger. Personally, if someone is
             | passionate about solving this problem, I would recommend
             | GraphQL, but it is up to each team to decide on what
             | solutions meet their requirements.
        
             | krschultz wrote:
             | The backend for frontend pattern is exactly why I got sold
             | on GraphQL. We had a pile of relatively low value server
             | code that could be replaced a GraphQL resolver and the
             | client got all of the advantages of that pattern. The move
             | to GraphQL genuinely freed up a lot of our time to work on
             | more important problems. This was on a smallish team so
             | that time mattered.
        
               | hardwaresofton wrote:
               | It looks like you've picked the right tool for the job in
               | that case, and I can't argue with that -- but the
               | submission is for tooling that people have created in
               | Swift for a problem that was already relatively solved by
               | OpenAPI bindings for Swift.
               | 
               | Would you mind going into what that low value server code
               | was doing? Was it simply aggregating results of multiple
               | requests? It's quite possible it wasn't that hard to
               | solve with slightly more intelligent (but not a
               | completely separate paradigm) code to start with. However
               | all-in-all I'm not out to argue that GraphQL doesn't
               | improve velocity. I'm saying that the tooling that it has
               | built in (pipelining, horizontal/vertical filtering, etc)
               | could have been available from REST, and gained all the
               | other benefits without a dramatic paradigm shift but no
               | one seems to have bothered, and instead we're finding
               | ourselves rebuilding bits that were already
               | available/worked out in OpenAPI land for a few features
               | that weren't too far away/hard to implement there.
        
               | magic_quotes wrote:
               | There is no different paradigm. Both GraphQL and "REST"
               | as it's usually implemented are RPC protocols. GraphQL
               | just doesn't pretend it is not.
        
           | Ozzie_osman wrote:
           | If you just want the syntax and caching, you might try React
           | Query. Haven't used it myself but it looks like it's Apollo-
           | inspired.
        
         | rand_r wrote:
         | Does OpenAPI have a way for the client to whitelist fields? I
         | see that as a major selling point for GraphQL.
         | 
         | Without it, you end up having to create tailored endpoints for
         | each use-case vs. for example a single "user" endpoint/vertex
         | that supports the complete buffet of fields for all use-cases
         | in one convenient place.
        
           | hardwaresofton wrote:
           | I can't say that it _should_ have that feature -- I 'd say
           | that is outside the purview of OpenAPI itself, but it could
           | definitely be built in in a repeatable and scalable way
           | pretty simply. I can tell you that tools like PostgREST have
           | had this for a long time[0].
           | 
           | [0]: https://postgrest.org/en/v7.0.0/api.html#vertical-
           | filtering-...
        
         | humbleMouse wrote:
         | 100% agree. People also need to remember that GraphQL was
         | originally written for server side javascript, and now it's
         | being ported to other languages(for what reason???).
         | 
         | You can create your own global json schema and build a ratchet
         | version of GraphQL using proven orms in about 20 minutes using
         | an unpersisted "filtering" field.
         | 
         | If you want automatic access to your data, bite the bullet and
         | do something cool like implement Apache Dremio.
        
           | santialbo wrote:
           | GraphQL was released as an specification with a node example
           | implementation. It wasn't "written for server side
           | javascript".
        
             | humbleMouse wrote:
             | Ok, so it was software released with it's first
             | implementation written in node.
             | 
             | And now have "Apollo", which is a server that runs inside a
             | v8 engine(node).
             | 
             | It seems to me that the javascript crowd are the ones
             | pushing this forward and seems to me that it was written
             | with javascript as a first class citizen.
             | 
             | Hard pass
        
         | dmitriid wrote:
         | The one place where I've found GraphQL to be potentially useful
         | is back office. This is usually the place where you need a lot
         | of very different data in one place, and in ways that are
         | completely different from customer-facing apps or sites. And
         | back office usually doesn't get as much love.
         | 
         | So usually you have backoffice devs scrambling to retrieve data
         | in weird ways from existing APIs. And things like "does this
         | inventory item come from a provider with an active contract,
         | and who else is on that contract" become ... weird and
         | unwieldy. This is where GraphQL with it's ad-hoc queries
         | definitely helps. And since the volume of queries in back
         | office is low, you don't worry too much about the performance
         | of some of the queries.
         | 
         | I wouldn't use it for anything else though.
         | 
         | Anecdata:
         | 
         | Just last month it took me about half an hour to implement an
         | "omni search" functionality in GraphQL that takes string as
         | input, coalesces results from three different backend APIs and
         | return back a nice view to fuzzy-ish search for three different
         | entities in our backend. Frontend couldn't be happier.
        
         | monadic5 wrote:
         | > Another week, another submission that hopefully edges more
         | people towards realizing that they've just created an under-
         | standardized, under-powered SQL-with-braackets that forces you
         | to bring your own query optimizer, and eschews the advancements
         | of Swagger/OpenAPI, JSONSchema, HAL, JSON-LD and the
         | flexibility of HATEOAS.
         | 
         | Why the insistence on condescending towards people who make
         | decisions you don't understand? It's one of HN's less
         | attractive aspects.
        
         | erikpukinskis wrote:
         | Does OpenAPI support multiple kinds of data in a single HTTP
         | request? I couldn't find anything about that in the docs.
        
           | hardwaresofton wrote:
           | AFAIK there is not a standardized way to do this but there's
           | no reason it can't -- you are free to define your own
           | Content-Type or use framed binary, or whatever else. If you
           | already have schemas on either side (or code to do dynamic
           | discovery), and a way to pack/unpack you can send different
           | kinds of data across.
           | 
           | This is less ideal than GraphQL in this case, since GraphQL
           | has done this hard work and standardized it/created the
           | conforming reference clients/servers already.
        
         | erikpukinskis wrote:
         | I don't really think of GraphQL as a data querying language
         | like SQL.
         | 
         | I think of it as a domain querying language.
         | 
         | SQL is meant to allow you to write queries to your data model
         | which are:
         | 
         | - arbitrary, and
         | 
         | - efficient
         | 
         | I don't think of GraphQL that way. I think of it as the place
         | where you encode your set of valid domain actions (i.e. not
         | arbitrary). And I don't think the consumers of the GraphQL API
         | should think about efficiency. They should just specify what
         | data they need and then the backend is responsible for figuring
         | out how to query the data model efficiently.
         | 
         | In other words, I don't really see any overlap between GraphQL
         | and SQL in terms of the role they play in a stack.
         | 
         | One helpful thing this distinction allows, is type inference.
         | You can trivially write a type generator that gives you the
         | type signature of a GraphQL query in any language. This is
         | precisely because of its limitations. That allows you to
         | automate the validation of your frontend and backend speaking
         | the same language.
         | 
         | You can't easily infer the return types of arbitrary SQL
         | queries. To me, that highlights the different purposes of the
         | languages.
        
           | hardwaresofton wrote:
           | If we consider GraphQL to be a domain querying language, what
           | have we gained over REST? You are free to model endpoints in
           | REST according to your domain (and deal with complexity
           | behind the facade), and I'd argue that REST can offer an even
           | more ergonomic DSL interface if you just write whatever you
           | want (s-expressions, let's say) and pass them to some POST
           | endpoint that reads your DSL and parses it. If the idea of
           | writing the DSL and POSTing it, parsing it, and doing the
           | very specific logic you want sounds wrong to you, it seems
           | like GraphQL should also similarly wrong. If it sounds good
           | to you, then is GraphQL far enough?
           | 
           | > I don't think of GraphQL that way. I think of it as the
           | place where you encode your set of valid domain actions (i.e.
           | not arbitrary). And I don't think the consumers of the
           | GraphQL API should think about efficiency. They should just
           | specify what data they need and then the backend is
           | responsible for figuring out how to query the data model
           | efficiently.
           | 
           | This is how SQL works, so there is some overlap there.
           | Optimizing SQL queries is might be a performance-seeking
           | operation, but SQL is declarative, and it is left largely to
           | the query optimizer to make your queries run fast. You can
           | _help_ the query optimizer make the query run fast, but that
           | 's all you can do -- and I can guarantee you that doing query
           | optimization has not gone away due to GraphQL, you've just
           | pushed the problem somewhere else, or you're forgetting the
           | bits of your API that you've modeled awkwardly in order to
           | avoid performance degradation/difficult-to-write resolvers.
           | 
           | But I think we're a bit off-track here -- GraphQL and REST is
           | at a different level of abstraction than SQL. My point is
           | that we've taken a step back from what we had already with
           | REST rather than that people should be using SQL on the
           | front-end. I think GraphQL is doomed to attempt to reach
           | expressive parity with SQL but that's another conversation
           | all-together.
           | 
           | > One helpful thing this distinction allows, is type
           | inference. You can trivially write a type generator that
           | gives you the type signature of a GraphQL query in any
           | language. This is precisely because of its limitations. That
           | allows you to automate the validation of your frontend and
           | backend speaking the same language. > > You can't easily
           | infer the return types of arbitrary SQL queries. To me, that
           | highlights the different purposes of the languages.
           | 
           | Most sufficiently ORMs can also give you this, and in other
           | languages there are libraries that will compile-time-check
           | the arbitrary SQL queries you write and won't compile if
           | they're invalid. What you need to have that kind of thing
           | work is sufficient type-checking power (Typescript offers
           | this) and sufficiently rich metadata (there are some examples
           | in the haskell[0] and rust[1] worlds). It wasn't necessary to
           | throw away REST to get these kinds of benefits. I've been
           | quite happy with TypeORM for example, and it would form a
           | good base for this kind of effort -- I don't know a library
           | that's already doing it, but this actually isn't as hard as
           | you think, especially for the simple case.
           | 
           | I'd argue that there is no difference (without too much
           | evidence, to be fair, as I am not an expert in inner working
           | of GraphQL) in the difficulty or parsing and validating a
           | GraphQL query for the simple case (i.e. the actual subset of
           | SQL that GraphQL represents) than actual SQL.
           | 
           | [0]: https://hackage.haskell.org/package/postgresql-
           | typed-0.6.1.2...
           | 
           | [1]: https://github.com/launchbadge/sqlx
        
             | RussianCow wrote:
             | > If we consider GraphQL to be a domain querying language,
             | what have we gained over REST?
             | 
             | Part of the value is in standardization. Yes, you can get
             | most of the benefits of GraphQL by creating your own layer
             | over REST, but then you've just written a badly specified,
             | bug-ridden version of GraphQL. The latter has enough
             | momentum that there now exist tons of tools for working
             | with it, which obviously wouldn't be true for anything you
             | build yourself.
             | 
             | > Most sufficiently ORMs can also give you this, and in
             | other languages there are libraries that will compile-time-
             | check the arbitrary SQL queries you write and won't compile
             | if they're invalid.
             | 
             | You're missing the point here: GraphQL gives you type
             | safety _between the server and client_. This has nothing to
             | do with ORMs or your database. What this means is that,
             | when building your web (or Android, or iOS, or
             | refrigerator, or whatever) frontend, you can guarantee the
             | type of every part of your query before even executing it.
             | This is a powerful guarantee, and paired with something
             | like GraphiQL[0], it allows for a level of exploratory
             | programming that isn 't currently possible with REST.
             | 
             | [0]: https://graphql.org/swapi-graphql
        
               | hardwaresofton wrote:
               | > Part of the value is in standardization. Yes, you can
               | get most of the benefits of GraphQL by creating your own
               | layer over REST, but then you've just written a badly
               | specified, bug-ridden version of GraphQL. The latter has
               | enough momentum that there now exist tons of tools for
               | working with it, which obviously wouldn't be true for
               | anything you build yourself.
               | 
               | Right, and you could have done this standardization
               | somewhere else right -- GraphQL is a NIH version of what
               | could have existed on top of well-considered existing
               | standards.
               | 
               | > You're missing the point here: GraphQL gives you type
               | safety between the server and client. This has nothing to
               | do with ORMs or your database. What this means is that,
               | when building your web (or Android, or iOS, or
               | refrigerator, or whatever) frontend, you can guarantee
               | the type of every part of your query before even
               | executing it. This is a powerful guarantee, and paired
               | with something like GraphiQL[0], it allows for a level of
               | exploratory programming that isn't currently possible
               | with REST.
               | 
               | I was responding to the point the person made in
               | particular, I'm aware of the mismatch in tiers, but their
               | question was specifically about being able to infer types
               | from SQL queries. They were comparing SQL to GraphQL.
               | There is nothing stopping you from using compile-time-
               | checking on the client side, if you use something like
               | TypeScript, which is why the rest of the surrounding
               | example was given.
               | 
               | This also _is_ related to the database, because the
               | original point was that people go GraphQL - > Resolver ->
               | DB, rather than HTTP -> HTTP Endpoint -> DB, and because
               | they have chosen GraphQL, they must now write efficient,
               | general resolvers that are essentially hand-built query
               | optimizers whereas with REST you can build with higher
               | granularity and usually higher, easier-to-achieve
               | efficiency.
               | 
               | You can guarantee every part of your query with REST as
               | well, if what you mean is you can avoid writing an
               | invalid query -- Typescript + generated OpenAPI client
               | libraries do this very well -- it's not unique to
               | GraphQL.
        
               | RussianCow wrote:
               | > Right, and you could have done this standardization
               | somewhere else right -- GraphQL is a NIH version of what
               | could have existed on top of well-considered existing
               | standards.
               | 
               | Maybe, but I think building GraphQL on top of REST would
               | have produced something much more convoluted and verbose.
               | As an example, see the OData standard[0], which, at least
               | from the client's perspective, is unnecessarily complex
               | compared to GraphQL. There may be cleaner ways to
               | structure this, but I'm not aware of any such attempts,
               | and I doubt you'd get a result as easy to use and
               | understand as GraphQL.
               | 
               | > This also _is_ related to the database, because the
               | original point was that people go GraphQL - > Resolver ->
               | DB, rather than HTTP -> HTTP Endpoint -> DB, and because
               | they have chosen GraphQL, they must now write efficient,
               | general resolvers that are essentially hand-built query
               | optimizers whereas with REST you can build with higher
               | granularity and usually higher, easier-to-achieve
               | efficiency.
               | 
               | That's fair, but as you pointed out earlier, you're just
               | shifting complexity around in any case. REST is simple
               | because it's so granular, which is great when all of your
               | data needs are met by that granularity. As soon as you
               | have more complex data requirements, you end up either
               | making ad hoc endpoints or evolving your API into a giant
               | monstrosity so that you can handle the more general
               | cases. GraphQL significantly simplifies this
               | implementation on both the client side and the API side.
               | Yes, the tradeoff is that now you need to optimize your
               | data access manually, but as others have said, there are
               | now tools for dealing with this issue--and it's not like
               | you don't gain anything from it.
               | 
               | For a simple but concrete example, if I need to fetch
               | data from ten different entity types in order to render a
               | page in my web app, I can do so in a single GraphQL query
               | and handle caching, etc in one pass, as opposed to
               | needing ten different REST calls and having to
               | consolidate them by hand. On top of the maintainability
               | benefits of this approach, the productivity gains are
               | huge.
               | 
               | [0]: https://www.odata.org/
        
           | codenesium wrote:
           | When your backend is sql how can you even do this
           | efficiently? Databases require indexes. If you can query
           | anything then there are performance bombs all over the place.
           | It's different if you're querying elastic I guess.
        
             | jkrems wrote:
             | > If you can query anything [...]
             | 
             | The answer is simple: You can't. GraphQL _in general_
             | doesn't allow arbitrary queries. It allows arbitrary output
             | field selection. But the filters are very explicit. It's
             | more "pre-aggregation of request waterfalls and masking of
             | outputs" than "querying a database".
             | 
             | Doesn't stop people from exposing their SQL databases
             | directly from GraphQL by generating a "free-for-all"
             | schema. And when they do - yep, that's definitely a
             | performance bomb and not a good use of GraphQL.
        
               | dmitriid wrote:
               | > The answer is simple: You can't. GraphQL _in general_
               | doesn't allow arbitrary queries.
               | 
               | It really does. Surely, it somewhat limits the data that
               | you get from it by defining a schema. But the moment you
               | allow any nesting/connections between data in that
               | schema, hello n+1 problem.
               | 
               | And then every discussion of this problem on HN or
               | elsewhere exposes the ugly truth: almost everyone uses
               | GraphQL as a REST endpoint in production by limiting the
               | actual queries you can run and curbing nesting.
        
               | andrewingram wrote:
               | The n+1 problem has solutions though. The most well-known
               | solutions may not suit your architecture, but please can
               | we stop pretending they don't exist?
               | 
               | GraphQL has been public since June 2015, and there's been
               | at least one solution to the n+1 problem (Dataloader)
               | since September 2015. If you were using pure REST
               | endpoints (just resources, no nesting/traversal) this is
               | the exact problem you'd be punting over to the client to
               | solve -- all that GraphQL is doing here is moving it back
               | onto the server. The actual amount of work is the same,
               | you just get faster response times.
               | 
               | Most implementations of GraphQL I've seen in different
               | languages provide some variation on the Dataloader
               | pattern. I'll fully concede it can be a hassle to set it
               | up correctly, but it _works_.
        
               | dmitriid wrote:
               | > The n+1 problem has solutions though.
               | 
               | It does. But it also means that the problem _exists_. It
               | 's there, you run into it _by default_ , and you have to
               | take special care to make sure it doesn't happen. And
               | data-loaders are just a first step. Some systems try to
               | actually calculate query complexities and nesting depth.
               | 
               | > this is the exact problem you'd be punting over to the
               | client to solve -- all that GraphQL is doing here is
               | moving it back onto the server. The actual amount of work
               | is the same
               | 
               | Exactly. The complexity doesn't go anywhere.
               | 
               | I... don't know how all this is an argument against what
               | I said.
        
             | erikpukinskis wrote:
             | I never fully solved this problem, so don't trust me, but I
             | can tell you what I learned...
             | 
             | I think for one thing you can't really rely on joins for
             | query efficiency, because as you say there are too many
             | combinations so it's impossible to optimize everything.
             | 
             | Instead you have to try to query each data type separately.
             | So you get a query for users. You do an SQL call and gather
             | up a bunch of requests for offices, and then you do a
             | single request to your office backend.
             | 
             | I think the best case is something like n SQL queries per
             | request, where n is the depth of the tree you are querying
             | (users->office->address is depth 3).
             | 
             | That means you're doing all your queries after the first
             | one by ID (not by arbitrary columns). So you have to have
             | some way to "pre-join" your tables. You can do this either
             | by optimistically joining your data to everything around it
             | (query the node plus all of its edges) or you need to store
             | your edges in your data model (which I have to assume is
             | what FB does).
             | 
             | In the end your resolvers need to be using some
             | standardized way of grabbing objects by is (or edge),
             | something like https://github.com/graphql/dataloader
             | 
             | Whether it's possible to do this efficiently I don't know.
             | At my last job we messed it up, and then we started
             | applying a strategy like I described above, but then I
             | switched jobs.
             | 
             | Would love to hear from others who have dealt with the same
             | challenges.
        
             | flashgordon wrote:
             | So SQL is _not_ a database :). It is a data access DSL that
             | is implemented by databases. SQL being untyped I dont think
             | is true - the table schemas _are_ types (albeit basic
             | product /record types). Inferring the type of a result is
             | quite reasonable if you start with the schemas. SQl suffers
             | from a UX problem for sure.
        
           | carlps wrote:
           | > And I don't think the consumers of the GraphQL API should
           | think about efficiency. They should just specify what data
           | they need and then the backend is responsible for figuring
           | out how to query the data model efficiently.
           | 
           | That is the point of the SQL language. It's declarative. You
           | define what you want your data to look like and the query
           | planner handles the actual fetching of the information in the
           | most efficient way it can. Obviously it's not perfect and you
           | still have to have someone who knows what they're doing to
           | define schemas that make sense and indexes where appropriate,
           | but that is a separate job from defining what data is needed.
        
             | Someone wrote:
             | Nitpick: it isn't SQL that lets you define what you want
             | your data to look like, but DDL
             | (https://en.wikipedia.org/wiki/Data_definition_language)
             | 
             | SQL (https://en.wikipedia.org/wiki/SQL) as the name
             | implies, is just for querying.
             | 
             | I don't see huge benefits for GraphQL. It's a query
             | language without a good query planner, so APIs will be
             | limited in the kind of queries they support. In that sense,
             | it's similar to restricting callers to a fixed set of
             | stored procedures instead of full SQL.
             | 
             | That's a viable idea, but it can also easily be implemented
             | in REST or using a JDBC connection.
             | 
             | IMO, the main benefit of GraphQL is that it allows the
             | caller to specify what fields it wants to see returned.
             | That means the implementation doesn't have to send
             | information the caller doesn't need, decreasing bandwidth,
             | and also doesn't have to provide a zillion endpoints (give
             | me only the address of user 'foo', give me address and
             | telephone number of user 'foo!', give me address and
             | birthday of user 'foo', etc.) that have to be maintained at
             | the caller's whim ("we also need the user's hair color").
             | That, however, doesn't need a full query language. REST
             | could easily be extended to support it.
             | 
             | Yes, you could also allow fairly free form GraphQL queries,
             | but if you do, you need a query planner (and, with it, the
             | statistics and metadata that help the query planner
             | perform), or end up with a rat's nest of special cases that
             | has to be updated for every new type of query.
        
             | ritchiea wrote:
             | The great thing about GraphQL is that it's declarative and
             | you have to write your own actual logic to define how the
             | fetching of information works! It only does half the work
             | SQL does! Everyone should switch to GraphQL ASAP!
        
       ___________________________________________________________________
       (page generated 2021-02-22 23:02 UTC)