4 ms·
I feel that, in typed languages, the only GraphQL oriented code you should be writing is the schemas and the resolvers. Manually implementing the models in your
by 013a 9y ago
I feel that, in typed languages, the only GraphQL oriented code you should be writing is the schemas and the resolvers. Manually implementing the models in your language's type system seems unnecessary and is a recipe for mistakes and drift between the schemas and those types.
- wyattjoh 9y agoHow would you represent more complex types? It would work fine if your models are flat and containing only POD, but if it contains something like GeoJSON (from Postgres for example), it would be pretty difficult to ensure that the serialization works properly.
- 013a 9y agoI'd imagine any decent library would provide an escape hatch around the codegen, so you can specify your own types if you'd like. The other option is to only write the Go types, then use codegen to generate the GraphQL schemas. In a way, I prefer this because it keeps everything in the same language, using all of the great tooling Go has. There is some prior art for this; the Juniper [1] Rust library. [1] https://github.com/graphql-rust/juniper https://github.com/graphql-rust/juniper
- sorenbs 9y agoIt's worth keeping in mind that GraphQL often finds itself in organisations that use multiple languages. A trend we have seen starting to emerge over the last 6 months is that backend teams write core business logic in languages like Java or Python and want to expose this as GraphQL microservices. Then you either have a central team responsible for the public GraphQL API. They will typically write a server in Javascript that composes all the microservices. Or alternatively you have multiple product teams that all want separate GraphQL APIs tailored to their use case. They too typically use Javascript for the server. When multiple languages are involved it turns out to be really useful to be able to use GraphQL SDL as the canonical representation and use code-gen on each stack. This is the use case GraphQL binding is intended for: https://github.com/graphql-binding/graphql-binding https://github.com/graphql-binding/graphql-binding
- vektah 9y agoI explored going type first before writing this and you could get pretty close. The details get hard though, how do you represent unions vs enums? even knowing what implements an interface? default arguments? directives?
- a-saleh 9y agoI think I would rather write types and derive schemas. Not sure if it were possible to derive resolvers?
- 013a 9y agoThere's a good argument that GraphQL can become the single SDL you use to define the API of many services written in many different languages. In this sense, it makes sense to write GraphQL and generate the language constructs; kind of an "outside->in" approach. If you're codegening your API from language constructs, the API will inevitably begin to use patterns that make sense in your language, not patterns that are universal to GraphQL or your entire system. That being said, I don't agree with it. I'm not a fan of GraphQL for inter-service communication; it makes sense at the internet API boundary, but once you're inside your service mesh I prefer something simpler and easier to test, like gRPC.
- vektah 9y agographql is just one representation of your applications data, it shouldn't dictate your models. I'm thinking about adding something that generates a model if it doesn't exist, but after its generated it becomes the users problem to keep it in sync. > recipe for mistakes and drift between the schemas and those types. The type system enforces there is no drift, it won't compile if its not perfect.
- theswan 9y agoAt Samsara our golang graphql implementation (https://github.com/samsarahq/thunder https://github.com/samsarahq/thunder) works this way. We write out resolver functions using plain old go types and use some reflection magic at startup to compute the graphql type information. Our docs are a bit spare at the moment, but this means with code like: type User struct { Id int64 Name string } func rootUser(ctx context.Context, args struct { id int64 }) (*User, error) { // ... } schemaRoot.FieldFunc("user", rootUser); We can derive the graphql SDL types automatically (looking at the arguments and return values) and use them with other graphql tooling, but it saves folks time from writing out a separate schema and keeping it in sync.