A small unstructured mini-thread/mini-rant on GraphQL.
I’ve now completed server prototypes for roughly the same functionality in C#, Java, Go (twice), Elixir, and nodejs.
GraphQL exemplifies everything that’s wrong in the industry :D
1/
First, it’s supposed to bring together data from different sources, right?
All GraphQL libraries have no proper examples of that. “Let’s create an array of values and serve that”. No one ever does that in real life.
As a result in reality everything is double the code 2/
Why? Because you get your data from an external service. And usually you present this data in an only slightly different way in GraphQL.
External service may provide a client with a contract id, but you present a client with a full contract from another external service 3/
Oh, screw you. Create a separate model/entity to deserialize the external service’s data, then write a separate model/entity in your GraphQL schema. And often run a generator on that schema to create a third model/entity just because.
4/
It’s both significantly worse and significantly better if you don’t go schema first, but define your schema in code. This can be anything from Java’s bearable fluent interface to go-graphql’s horror show.
5/
In schema-first though it often happens that if you need some custom resolver on a single field, nope, you have to write your own model/entity by hand, and probide resolvers on that. Because screw you.
Looking at you gqlgen
6/
You’d think code-first would work. I mean, whatevr you write in code is what you want/need, right?
Wrong.
Enter Elixir’s Absinthe. Schema fields are defined in snake_case. Gets automatically converted to camelCase when requested through GraphQL.
WHY?!
It gets worse 7/
This only happens with data that Absinthe itself sends. But… you get that data from external sources, and those will often have field names in camelCase.
You have to… transform those field names manually to snake_case before providing it to Absinthe.
Because screw you 8/
Goddamn dates.
Everyone needs to work with dates and timestamps. Why the fuck GraphQL (and protobuf) don’t have Date, DateTime, Time and Timestamp in their specs?
Becuase their authors have never been in the real world it seems. As a result every single library ends up … 9/
… you though I’d say “implementing those as custom GraphQL scalars”. Oh, sweet summer child.
Some will onlly have DateTime. Some, like Apollo, will have two pages of explanations and code examples but not include it in the lib by default. 10/
Some will have them as external libraries that need to be injected and will screw up things like JSON (de)serialzation. Looking at you, graphql-java-extended-scalars. 11/
Some don't implement Date, DateTime etc. “because it’s not in the graphql spec”.
Spec is bad, you exist not to please the spec, but to help people make things. People. 12/
Schemas.
Code-first crowd is notorious for not being able to generate the final schema. You need some external tools that will connect to the running server, introspect the schema, and generate the schema based on that.
I literally can’t even
13/
Dataloading.
Some libs think that dataloading is for others to implement. Perhaps. Is there a better way to hook up a dataloader than providing an untyped context object, and then returning a function calling function wrappers from that object in your resolve function?
14/
The whole idea that resolvers should be able to call external services (that’s why they are there to begin with!) is almost a foreign concept in a surprising number of libs.
You can always go the Java route and inject everything everywhere, including your eyeballs. 15/
Many of these issues stem from language and conventions: Java must have beans, and registries, and dependency injection, and config objects, and profiles, and…
Go’s lack of generics leads to 1500 interfaces that are the same thing. Or casting unnamed interfaces to things 16/
Apollo is only marginally better than the rest of the crowd just because JS doesn’t care what objects you through at it.
But yeah, it will not provide useful scalars out of the box because you, the programmer, are meant to suffer
17/
Errors. Oh god, I forgot errors.
Helpful messages are for losers. Figure out “Can’t query field id on type X” yourself, you child.
Stacktraces are for losers. None will be included in the error messages, in any lib IIRC. When something fails, who cares where it fails 18/
Some will gladly dump HTML at you when you accidentally retrieve a 404 page in an external service. Others will “JSON decode error: invalid symbol p at 1:30” at you.
No other messages. It’s your job to write perfect resolvers on the first try, you incompetent turd
19/
I still think GraphQL is bad for external APIs for various reason, to lenghy to list here.
But for the backoffice and exploratory APIs it could be a very nice tool. Especially since backoffice is the one place that has to deal with backend APIs in the frontend
20/
But Christ Almighty, is it ever so painful to write a backend server that prvodes a GraphQL wrapper for your backend APIs in a straghtforward concise manner that doesn’t make your eyes bleed and doesn’t take you on an accelerated path to clinical depression.
21/21
@threadreaderapp unroll, please