Why are there "two names" for each GraphQL query/mutation? - graphql

I am learning GraphQL and one basic point has me puzzled. I know there is an easy explanation, but I can't find it. Specifically, from the Apollo documentation (https://www.apollographql.com/docs/apollo-server/essentials/data.html#operation):
...it makes sense to name the operation in order to quickly identify
operations during debugging or to aggregate similar operations
together...Operations can be named by placing an identifier after the
query or mutation keyword, as we’ve done with HomeBookListing here:
query HomeBookListing {
getBooks {
title
}
}
If HomeBookListing is the name of the query, what, then, is getBooks? The name of the resolver?
Similarly, when you pass variables to a query, why are there "two levels" of parameters, like this
mutation HomeQuickAddBook($title: String, $author: String = "Anonymous") {
addBook(title: $title, author: $author) {
title
}
}
So, would $title: String, $author: String = "Anonymous" be the variables passed to the query, and title: $title, author: $author variables passed to the resolver?
Of course I can memorise the pattern, but I'm keen to understand, conceptually, what the different pieces are doing here. Any insights much appreciated!

You may find it helpful to review the spec, but what follows is a somewhat shorter explanation:
What is an operation?
There are three operations in GraphQL (query, mutation and subscription). Typically, a GraphQL request consists of only one of these three operations, and it forms the root of the request, or the entry point into the rest of the schema.
Each operation has a single object type associated with it. By convention, these types are named Query, Mutation and Subscription, but their naming is functionally irrelevant to your schema. Other than their association with a particular operation, there's nothing special about these object types -- each has a name, description and fields just like any other object type in your schema. Collectively, we call these three types root operation types.
In your example, the query root type has a field called getBooks. That field is resolved according to the same rules as any other field in your schema. The only special thing about this field is that it's at the root -- there is no "parent" field that was resolved before it.
Operation names are optional because they do not impact the data returned by the server -- they are there generally for debugging purposes (although some clients and tools use them to provide other features, so it's always good to have them). Specifying at least one field name for your root operation type, however, is necessary, otherwise your operation would not actually do anything (i.e. query the server for the data). Again, these fields are your entry point into the rest of the schema and the starting point for your data graph.
Ok, but what about the variables?
According to the spec:
Variables must be defined at the top of an operation and are in scope throughout the execution of that operation.
While we do not initialize a variable inside the document with a value, we do need to define it by telling GraphQL what the type of the variable it is. This allows GraphQL to then validate the usages of your variables throughout the document. For example, if you define a variable as a String and then attempt to use it at an input field that is an Int, validation will fail and your request will blow up before it is even executed.
Variables are always defined as part of the operation definition -- they can be used anywhere in the document, though, even multiple times. So there are no "two levels of parameters" here -- one line is simply the definition, the other line is usage.
A word on semantics
Even though we have a spec, the language around GraphQL has evolved past the terms outlined inside it. The term "query" has taken on multiple meanings that you may encounter while reviewing various docs and articles. It helps to keep these definitions in mind to avoid getting confused:
By convention, we name the root operation type associated with the query operation the Query type
Informally, the fields on that Query (i.e. getBooks) that are often referred to as the "queries" of your schema (just like the fields on the Mutation type are often called the "mutations" of your schema.
The complete request string we send to the server, which includes the whole operation and any relevant fragments is officially called the document. However, we often refer to making a request as querying your server. This has led to the document itself often being called a query, whether the operation is contains is actually a query or a different operation like a mutation.

Related

Will graphql run resolver with additional arguments

If graphql query schema is like this:
user(user_id: Int): User
Will apollo run resolver if in query will be additional (email) argument not defined in query schema?
I want iterate arguments in resolver, but not sure if it possible to pollute them.
P.S. If there is documentation of how apollo parcing arguments, will appreciate.
In GraphQL, a schema defines what fields are available to the client, including what arguments are available for that field and what the types of those arguments are. Any query submitted to a GraphQL service will first be validated before it's executed. If the query includes any extraneous arguments, it will fail validation and won't be executed. This is explained here in the spec:
Formal Specification
For each argument in the document
Let argumentName be the Name of argument.
Let argumentDefinition be the argument definition provided by the parent field or definition named argumentName.
argumentDefinition must exist.
Explanatory Text
Every argument provided to a field or directive must be defined in the set of possible arguments of that field or directive.
For a better idea of how GraphQL works, I would suggest taking at least a cursory look through the spec.

Why is TYPE_ADDED_TO_INTERFACE considered a breaking change?

I am using the Apollo Server implementation of GraphQL, together with the Apollo Engine, and specifically the functionality to check whether a schema diff contains any breaking changes. I'd like to understand better why TYPE_ADDED_TO_INTERFACE is considered to be a breaking change, and if anyone can provide an example of a graphql query that would break, as a consequence?
I'm using the apollo/2.9.0 darwin-x64 node-v10.10.0 to perform the schema check with the apollo service:check command.
For example, if I have this schema:
interface Animal {
id: ID
}
type Dog implements Animal {
id: ID
favoriteToy: String
}
And then add this to the schema:
type Cat implements Animal {
id: ID
}
This is considered a breaking change. Why?
I can see that if someone is making a query for all the Animal objects, and has a ... on Dog fragment in the query, they would start getting Cat objects back with only the interface fields, until they also add a ... on Cat fragment. Is that what's considered breaking?
Having a type implement an interface it previously did not should not break existing queries. To your point, even if the inline fragment is omitted, the results will still be valid (they could result in an empty object being returned if no interface fields were selected, but that's still a valid response).
I could, however, foresee issues in specific clients resulting from this kind of change. For example, when using Apollo client, we often create an IntrospectionFragmentMatcher to specifically help the client correctly cache results from union or interface fields.
To support result validation and accurate fragment matching on unions and interfaces, a special fragment matcher called the IntrospectionFragmentMatcher can be used. If there are any changes related to union or interface types in your schema, you will have to update the fragment matcher accordingly.
In other words, having the schema change in this way could break client caching behavior. I suspect for clients that do schema-based code-generation, like apollo-android, this could also result in some runtime weirdness.

What's the difference between Operation Arguments and GraphQL variables?

I am in the process of learning GraphQL and have stumbled upon understanding the difference between Operation Arguments and GraphQL variables. Because IMO, both provide, client, the facility to pass in dynamic data to either mutations or queries etc.
Can someone enlighten me ?
Cheers!
Arguments and variables serve completely different functions.
Every field in a GraphQL schema can be configured to accept one or more arguments. For example:
query FilmQuery {
film (id: "ZmlsbXM6MQ==") {
id
title
}
}
Here the film field accepts an argument named id. Arguments are used to alter the value a field resolves to. In our example above, the server returns a different Film object based on the id value the client provides.
Arguments accept inputs, which can be either scalars, enums or more complex Input Object Types. Here, we're passing a String value of "ZmlsbXM6MQ==" to the argument. By writing out the value inside the query, we are said to be using a literal value.
There is nothing wrong with using literal values in your queries, but when the value passed to the argument needs to be dynamic, we need something more -- we need variables.
Variables allow us to parameterize and reuse queries. Here's our example, rewritten using a variable:
query FilmQuery($myId: ID!) {
film (id: $myId) {
id
title
}
}
Variables must first be defined at the top of your document, as part of the operation definition. Here we've defined a single variable ($myId) and told GraphQL it's type is ID!. Once defined, variables can then be used anywhere inside the operation. The actual values of any variables used in your document must be sent along with the query itself when the client actually makes the request to the server.
Again, arguments only provide a way to change how a request is executed, while using variables as inputs to those arguments is what makes a particular query dynamic and reusable.
Please note that you could use string concatenation or template literals client-side to achieve a similar effect to what variables do. You should generally avoid doing so, however, because 1) it unnecessarily creates additional work for the client and 2) serializing inputs yourself, especially complex ones like Input Object Types, can quickly become complicated and error-prone.

Modelling calculated fields in Rest API

It is a common practice for Restful resources to support field selectors in the query string. For example, if a resource has fields A,B,C and D but the client is interested only in a subset of fields (say A and B) then the Url might look like
.../resource/1/?fields=A,B // only A and B are 'selected'
Now supposed we add another property to the resource. The thing with this property is that it does not have any physical storage. It is a computed value. Also suppose that this computation is very expensive.
Now obviously, Rest does not care about such things, whether data comes from a file a DB or a fancy algorithm.
But here comes a dilemma: the 'fields' query parameter is always optional. In my case, omitting 'fields' means "bring all the fields" (much like '*' in SQL):
.../resource/1 // A,B,C,D and E(xpensive) are 'selected'
I am positive that there are many existing clients that are using the naive approach (not bothering to specify an explicit list of fields). This means that adding this new heavy property will unintentionally create a performance break (possibly a very severe one).
What are the common techniques to cope with these situations?
Alternatives I considered:
Add a special notion to the system that says that querying with '*' semantics will not necessarily return ALL the fields (heavy fields will be omitted by default). If a client wants them- he must ask for them explicitly
Not to model these extra properties as fields on the resource. Instead expose a dedicated endpoint that will carry out the computation, thus eliminating possible confusion but introducing Rest-RPC style into the system.
Make it the cilent's problem: if he did not bother to be explicit in the first place, tough for him. That is not really an option- don't have this privilege.
I like option 1 best. I'd consider representing these fields as referenced object, and then you could get to them HATEOAS style, through separate calls for the heavy fields. This is similar to how web-pages behave -- return the framework and some content, then force extra calls if the user wants the images, videos, etc. –
Take a look at this: spring.io/understanding/HATEOAS, this: timelessrepo.com/haters-gonna-hateoas, and this: stackoverflow.com/questions/tagged/hateoas

Returning both computation result and status. Best practices

I was thinking about patterns which allow me to return both computation result and status:
There are few approaches which I could think about:
function returns computation result, status is being returned via out parameter (not all languages support out parameters and this seems wrong, since in general you don't expect parameters to be modified).
function returns object/pair consisting both values (downside is that you have to create artificial class just to return function result or use pair which have no semantic meaning - you know which argument is which by it's order).
if your status is just success/failure you can return computation value, and in case of error throw an exception (look like the best approach, but works only with success/failure scenario and shouldn't be abused for controlling normal program flow).
function returns value, function arguments are delegates to onSuccess/onFailure procedures.
there is a (state-full) method class which have status field, and method returning computation results (I prefer having state-less/immutable objects).
Please, give me some hints on pros, cons and situations' preconditions of using aforementioned approaches or show me other patterns which I could use (preferably with hints on preconditions when to use them).
EDIT:
Real-world example:
I am developing java ee internet application and I have a class resolving request parameters converting them from string to some business logic objects. Resolver is checking in db if object is being created or edited and then return to controller either new object or object fetched from db. Controller is taking action based on object status (new/editing) read from resolver. I know it's bad and I would like to improve code design here.
function returns computation result, status is being returned via out
parameter (not all languages support out parameters and this seems
wrong, since in general you don't expect parameters to be modified).
If the language supports multiple output values, then the language clearly was made to support them. It would be a shame not to use them (unless there are strong opinions in that particular community against them - this could be the case for languages that try and do everything)
function returns object/pair consisting both values (downside is that
you have to create artificial class just to return function result or
use pair which have no semantic meaning - you know which argument is
which by it's order).
I don't know about that downside. It seems to me that a record or class called "MyMethodResult" should have enough semantics by itself. You can always use such a class in an exception as well, if you are in an exceptional condition only of course. Creating some kind of array/union/pair would be less acceptable in my opinion: you would inevitably loose information somewhere.
if your status is just success/failure you can return computation
value, and in case of error throw an exception (look like the best
approach, but works only with success/failure scenario and shouldn't
be abused for controlling normal program flow).
No! This is the worst approach. Exceptions should be used for exactly that, exceptional circumstances. If not, they will halt debuggers, put colleagues on the wrong foot, harm performance, fill your logging system and bugger up your unit tests. If you create a method to test something, then the test should return a status, not an exception: to the implementation, returning a negative is not exceptional.
Of course, if you run out of bytes from a file during parsing, sure, throw the exception, but don't throw it if the input is incorrect and your method is called checkFile.
function returns value, function arguments are delegates to
onSuccess/onFailure procedures.
I would only use those if you have multiple results to share. It's way more complex than the class/record approach, and more difficult to maintain. I've used this approach to return multiple results while I don't know if the results are ignored or not, or if the user wants to continue. In Java you would use a listener. This kind of operation is probably more accepted for functinal languages.
there is a (state-full) method class which have status field, and
method returning computation results (I prefer having
state-less/immutable objects).
Yes, I prefer those to. There are producers of results and the results themselves. There is little need to combine the two and create a stateful object.
In the end, you want to go to producer.produceFrom(x): Result in my opinion. This is either option 1 or 2a, if I'm counting correctly. And yes, for 2a, this means writing some extra code.
My inclination would be to either use out parameters or else use an "open-field" struct, which simply contains public fields and specifies that its purpose is simply to carry the values of those fields. While some people suggest that everything should be "encapsulated", I would suggest that if a computation naturally yields two double values called the Moe and Larry coefficients, specifying that the function should return "a plain-old-data struct with fields of type double called MoeCoefficient and LarryCoefficient" would serve to completely define the behavior of the struct. Although the struct would have to be declared as a data type outside the method that performs the computation, having its contents exposed as public fields would make clear that none of the semantics associated with those values are contained in the struct--they're all contained in the method that returns it.
Some people would argue that the struct should be immutable, or that it should include validation logic in its constructor, etc. I would suggest the opposite. If the purpose of the structure is to allow a method to return a group of values, it should be the responsibility of that method to ensure that it puts the proper values into the structure. Further, while there's nothing wrong with a structure exposing a constructor as a "convenience member", simply having the code that will return the struct fill in the fields individually may be faster and clearer than calling a constructor, especially if the value to be stored in one field depends upon the value stored to the other.
If a struct simply exposes its fields publicly, then the semantics are very clear: MoeCoefficient contains the last value that was written to MoeCoefficient, and LarryCoefficient contains the last value written to LarryCoefficient. The meaning of those values would be entirely up to whatever code writes them. Hiding the fields behind properties obscures that relationship, and may impede performance as well.

Resources