ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.17k stars 737 forks source link

Justification for HotChocolate as opposed to GraphQl.Net #392

Closed jbray1982 closed 5 years ago

jbray1982 commented 5 years ago

Hello,

My company has begun a project using your library to implement a graphQl endpoint. However, questions have arisen as to why we should choose this library over GraphQl.NET.

I find it to be more trim, and the code comes out much prettier, but with enough effort we could make GraphQl.NET pretty too. I was wondering if you would be willing to share your reasons for developing this library when GraphQl.NET already exists.

Thanks for your time, Jason Bray

michaelstaib commented 5 years ago

I think both platforms are valid platforms. Moreover, my take is that there is room for two, three or even four for different takes on GraphQL for .net.

We started the project last year after we had decided that we would either have to invest a lot in GraphQL-DotNet or build our own platform. In the end we found building Hot Chocolate was the better way for us.

It is not that GraphQL-DotNet is a bad platform, but we thought we could bring something new to the table and make it feel better (this is subjective).

You can see this already with directives. Directives can be combined with a middleware in an effortless way. You can use these to replace regular resolvers or extend them. Moreover, you can chain them to a pipeline and so on.

type Query {
    foo: Foo @HttpGet(client: "fooClient") @json(path: "fielda.fieldb[1]")
}

type Foo {
    bar: String
}

A good example for the use of directives is our authorization layer: https://hotchocolate.io/docs/next/authorization

But this is just the beginning. With the next version we will make the query engine much more extensible. You can basically build your own query engine with the QueryExecutionBuilder, this combined with our new QuerySyntaxRewriter will built the foundation of our new schema stitching capabilities that will let you stitch together a schema from rest services, remote GraphQL endpoints or databases without a single line of c# code.

Ok, Ok there will be some code 

But stitching will be much easier than with Apollo or other GraphQL servers that we have looked at.

Moreover, with 0.7.0 we will close a lot of gaps to GraphQL-DotNet and start leading in some areas like schema stitching.

Furthermore, we are investing a lot in the schema-first and poco-approach. Basically, you can describe schemas in any way or even mix everything together.

Lastly, we are investing a lot more in our parser, which is more spec compliant and reliant than the current GraphQL-parser. As soon as a Spec feature hits draft stage, we are implementing it. So, with version 0.7.0 we are introducing four new draft features like repeatable directives. This means that now we are faster than GraphQL-DotNet in adopting new spec features.

So, it is still early days for Hot Chocolate which also gives you the chance to shape the API with us.

michaelstaib commented 5 years ago

Schema Stitching

michaelstaib commented 5 years ago

We have a slack channel if you want to go deeper into various aspects: https://join.slack.com/t/hotchocolategraphql/shared_invite/enQtNDkxMjA1MzkxNzMwLTFlMjUxMWQ2YWQ4ODRkYmI5MWJiMmNhNzI2MjQ4MzRmZjlhY2Y0Yjg0MzM1YTRhMDc4YWUwOTViMjNhNzY1ZGI

drowhunter commented 5 years ago

Let me also add to this. I think we are in the same boat. I also needed to choose between the two for my company project. And i spent 2 weeks on working with each one. back and forth.

What led me to choose HotChocolate is that..

If you need to restrict access to certain fields based on roles. policies Hotchocolate is the clear winner. In graphql-dotnet they treat authorization as validation so if the client doesnt have access to one field you get no data back .

Also hot chocolate can Infer your Graphql types automatically, ( you dont need to create types and fields for every property in your database) Graohql-dotnet does have an undocumented AutogeneratingObjectType class but it only supports scalar properties. And doesnt provide a meaningful way to override or hide fields you dont want to show.

I acutually submitted a pull request to those guys that made it similar to HotChocolate that was never accepted due to them not agreeing with the need for such a capability

https://github.com/graphql-dotnet/graphql-dotnet/pull/914

pkellner commented 4 years ago

@drowhunter It looks like your pull request has been acted on and there is now a feature in graphql to do this. Are you still happy with your hotchocolate choice? graphql-dotnet seems more mature but hard to tell. AutoRegisteringObjectGraphType

michaelstaib commented 4 years ago

I think at this stage this is no longer true (maturaty wise).

Join our slack channel and see for yourself.

The bottom line is HC is faster, easier, has more features and with the platform release (version 11) goes far beyond what GraphQL-DotNet has to over.

GraphQL-DotNet has the advantage of the name... which makes it more discoverable... but we wanted to be different and we stick with it.

pkellner commented 4 years ago

OK, you've got my attention. Besides being a group of obviously brilliant, very artistic and not very good at naming things, who are you? If a big company wants to use hotchocolate, do they have any reason to think that maltedMilkshakes might come along and that would be the end of hotchocalate? Do you guys have any big companies that are behind (or funding) your effort? I can't find any "about ChiilCream" that gives me a warm feeling of history, customers, etc.

OK, now to a real problem I'm wondering you solve better then the other guys. I'm finding that I need dataloader a for my problems and that the trivial case of a simple parent child only works in demos, not the real world. specifically, the problem is addressed and solved with closure and reflection in the other guys project, but it really feels ugly and not type safe at all. Have you guys though this dataloader scenario through better? Here is a link to the discussion. https://github.com/graphql-dotnet/graphql-dotnet/issues/560#issuecomment-392773682

michaelstaib commented 4 years ago

So, what is your concern with their approach? I read into their documentation and they basically do what every platform does.

We will divert in this regard with version 11. We are at the moment building a new execution engine that works completely different to the spec described execution algorithms.

Instead of execution the graph as is we ware precompiling queries to execution plans.

For that we do take into account a lot of knowledge about the schema like overlapping data for instance. But also the resources that you consume.

With that we are able to flatten the execution tree and to group resolvers more efficiently around shared resources.

With this we can in many cases skip defining explicit DataLoader.

We are still very busy on this one and will soon release more information about it.

michaelstaib commented 4 years ago

Regarding DataLoader... I recommend using them more like the following:

     public Task<Schema> GetSchemaByNameAsync(
            string name,
            [DataLoader]SchemaByNameDataLoader dataLoader,
            CancellationToken cancellationToken) => 
            dataLoader.LoadAsync(name, cancellationToken);

you can also use the delegate form and define them on the fly:

context.BatchDataLoader("foo", c => ...)

But in general I personally like to define them as a class.

michaelstaib commented 4 years ago

Also with Hot Chocolate filling in those fields in the relation is also very nice... you can this even do without declaring a schema type:

 [ExtendObjectType(Name = "Query")]
    public class SchemaQueries
    {
        [UsePaging]
        [UseFiltering]
        [UseSorting]
        public IQueryable<Schema> GetSchemas(
            [Service]ISchemaRepository repository) =>
            repository.GetSchemas();
    }

The type above adds a field schemas to the Query. also it adds paging, filtering and sorting, meaning that we can do the following:

{
  schemas(where: { name_contains: "foo" } first: 10) {
    edges {
       cursor
       node {
         name
       }
    }
  } 
}

The input object that is passed into the where argument is rewritten to a expression tree that is applied to the queryable that is then compiled to a native database query.

pkellner commented 4 years ago

I do like a lot how you use attribute. I do need to study more and go through your examples to understand what you've done but it does seem very powerful.

Regarding what I don't like about the dataloader, what I don't like is it feels awkward in terms first giving the function as a string, and then, having to create parameters that are inferred in closure. Maybe it is just me, but it feels like a code smell. Maybe I'm just not use to doing functional programming like that in c#.

My first question was about your company. I am serious about wondering more about the team behind HotChocolate. With so much s/w coming and going, as an independent consultant, people expect me to recommend things that will be around long term if they are going to invest hours of programming. That is, what I like about React and Angular is their are big companies that dependent on them (facebook and google). Vue worries me in that regard. Are there long term plans to build around HotChocolate to keep it going?

michaelstaib commented 4 years ago

There are at the moment 4 person working on the chillicream GraphQL platform. We hope to have the platform out by August ... maybe later. SwissLife in Switzerland is pushing us and they are investing in this platform. That have built there customer platform on top of Hot Chocolate and are at the moment pushing the schema registry. Then there are other like ThoughtWorks https://www.thoughtworks.com/radar/platforms/hot-chocolate or PushPay https://pushpay.com. There are more but these three I can tell you about.

sjwilczynski commented 3 years ago

@michaelstaib thanks for all the super valuable points already in this thread! Just wanted to ask if you maybe repeated the performance comparison with GraphQl.NET after they released the version 4, which contains a lot of performance improvements? Additionally, are there any new points that you would want to highlight as Hot Chocolate advantages over GraphQl.NET?

Asking as our team is in the middle of choosing the graphql library :)

michaelstaib commented 3 years ago

Yes, performance is a main concern of every release. We will with the release of version 12 release new numbers.

Hot Chocolate increased performance once more :)

The throughput performance increased from around 19000 requests per second in version 11 to 31000 requests per second. We saw the gains GraphQL .NET did with version 4.5 and are running performance tests agains the 4.5 core of their library. If we look at for instance Introspection which mainly looks at processing large results of nodes then we can see that Hot Chocolate only uses 43% of the memory GraphQL .NET does. Further more we process the same request for the same schema in 38% of the time GraphQL .NET uses.

| HotChocolate - IntrospectionQuery | 280.73 us | 74 KB | | GQLDotNet - Introspection | 723.41 us | 169 KB |

Hot Chocolate 12 uses on average 75% less memory than version 11 and processes 65% faster.

We are still working on some aspects here and hope to ship version 12 with tons of other new features in the next two weeks.

But its not only about performance. Hot Chocolate has a vertically integrated platform where every component is made by the team and gives you tools far beyond of any other GraphQL library.

With version 12 we are shipping out new version of our GraphQL IDE.

image

Further we are one of the most feature rich and simplest to use GraphQL platforms. Whenever a feature hist draft in the spec we are implementing and shipping it. We were the first GraphQL implementation to fully support the new defer and stream spec. With version 12 we are the first GraphQL server to ship the one oneof spec to support input unions. Apart from that with version 12 we now support out of the box cypher integration for graph databases, SQL Kata support, Entity Framework support, native MongoDB support and many more things.

Performance is at our core and we are committed to raise the bar with every release. We not only compare to GraphQL .NET but also to the rust implementation, Java implementation and any node implementation. With version 12 we will be at the top.

But I mean, this is a constant thing, an with the next version of Sangria or GraphQL-Java they could again catch up or overtake. The crucial thing is that we are working with 6 people constantly to push the platform forward.

With the release of HC12 we also will release new benchmarks, for this release we widened the aspects we tests and also look at batching performance.

Regarding, this, with version 12 Hot Chocolate has a complete new execution engine that now precompiles execution plans that will optimize the request that you do. The initial optimizations for version 12 are small but with the September release we update the schema federation engine of hot chocolate an will use the new engine to optimize overlaps and data fetching.

We will soon publish a blog series on the improvements of HC.