GraphQL - Anti Patterns in Schema design
@vilvaathibanpb
![](https://p10cdn4static.sharpschool.com/UserFiles/Servers/Server_208743/Image/twitter2.png)
- Vilva athiban p b
About me
JavaScript / GraphQL earns my bread
Travel and painting satisfies my thirst
Endless love for OSS but not committed to a single project for long 😉
Works @ Omio, A Search Engine for Travel
A Youtube series "Known Unknowns" - Vilva Athiban (Channel name)
@vilvaathibanpb
![](https://p10cdn4static.sharpschool.com/UserFiles/Servers/Server_208743/Image/twitter2.png)
Let's begin
@vilvaathibanpb
![](https://p10cdn4static.sharpschool.com/UserFiles/Servers/Server_208743/Image/twitter2.png)
![](https://data.whicdn.com/images/331175221/original.gif)
what is anti patterN ?
1. A commonly used process, structure, or pattern of action that despite initially appearing to be an appropriate and effective response to a problem, has more bad consequences than good ones.
2. Another solution exists that is documented, repeatable, and proven to be effective.
@vilvaathibanpb
![](https://p10cdn4static.sharpschool.com/UserFiles/Servers/Server_208743/Image/twitter2.png)
anti patters in schema design
- Nullable Fields
- Miscommunication in the Docs
- Lengthy arguments to Mutation
- Insufficient Mutation Response
- Allowing invalid inputs
- Schema - Circular Reference
- Massive data in response
Nullable Fields
![](https://i.imgur.com/Mw43Jio.gif)
#Sample Schema
type Passenger {
name: Name
age: Int
address: String
}
type Name {
firstName: String
secondName: String
}
<p>passenger.name.firstName</p>
#Breaks the UI without any errors during query
#Sample Schema
type Passenger {
name: Name!
age: Int
address: String
}
type Name {
firstName: String
secondName: String
}
<p>passenger.name.firstName</p>
# Throws error when queried
# and doesnt break the UI
Miscommunication in the Docs
![](https://25.media.tumblr.com/tumblr_m9fq59lVFe1r426i4o5_250.gif)
# Sample schema
type Passenger {
id: ID!
name: String!
age: Int!
address: String!
passengerId: ID!
}
# A single line, type-level description
"Passenger details"
type Passenger {
""" a multi-line description
the id is general user id """
id: ID!
name: String!
age: Int!
address: String!
"single line description: it is passenger id"
passengerId: ID!
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/906873/images/7330882/7X78V4qQ.png)
Lengthy arguments to Mutation
![](https://media3.giphy.com/media/j2pWZpr5RlpCodOB0d/giphy.gif)
type MutationResponse {
status: String!
}
type Mutation {
createPassenger(name: String!, age: String!, address: String!): MutationResponse
}
# Mutation in Frontend looks like:
mutation PassengerMutation($name: String!, $age: String!, $address: String! ) {
createPassenger(name: $name, age: $age, address: $address ) {
status
}
}
type MutationResponse {
status: String!
}
type Mutation {
createPassenger(name: String!, age: String!, address: String!, city: String!): MutationResponse
}
# Mutation in Frontend looks like:
mutation PassengerMutation($name: String!, $age: String!, $address: String!, city: String! ) {
createPassenger(name: $name, age: $age, address: $address, city: $city ) {
status
}
}
type MutationResponse {
status: String!
}
type PassengerData {
name: String!
age: String!
address: String!
}
type Mutation {
createPassenger(passenger: PassengerData!): MutationResponse
}
#Mutation in Frontend looks like:
mutation PassengerMutation($passenger: PassengerData! ) {
createPassenger(passenger: $passenger) {
status
}
}
type MutationResponse {
status: String!
}
type PassengerData {
name: String!
age: String!
address: String!
city: String!
}
type Mutation {
createPassenger(passenger: PassengerData!): MutationResponse
}
#Mutation in Frontend looks like:
mutation PassengerMutation($passenger: PassengerData! ) {
createPassenger(passenger: $passenger) {
status
}
}
Insufficient Mutation Response
![](https://thumbs.gfycat.com/MildGlaringInvisiblerail-max-1mb.gif)
type MutationResponse {
status: String!
}
type Passenger {
name: String!
age: String!
address: String!
}
type Mutation {
createPassenger(passenger: Passenger!): MutationResponse
}
# Mutation in Frontend looks like:
mutation PassengerMutation($passenger: PassengerData! ) {
createPassenger(passenger: $passenger) {
status
}
}
type MutationResponse {
status: String!
id: ID!
updatedPassenger: Passenger
}
type Passenger {
name: String!
age: String!
address: String!
}
type Mutation {
createPassenger(passenger: Passenger!): MutationResponse
}
# Mutation in Frontend looks like:
mutation PassengerMutation($passenger: PassengerData! ) {
createPassenger(passenger: $passenger) {
status
id
updatedPassenger
}
}
Allowing invalid inputs
-
Custom Scalars
-
Enums
Custom Scalars
![](https://i.pinimg.com/originals/9b/4c/cd/9b4ccdd597c4e4dc71cd02c676b9259b.gif)
Allowed scalars
- Int
- Float
- String
- Boolean
- ID
// Logic implementation for the Date type
import { GraphQLScalarType } from 'graphql';
import { Kind } from 'graphql/language';
const resolverMap = {
Date: new GraphQLScalarType({
name: 'Date',
description: 'Date custom scalar type',
parseValue(value) {
return new Date(value); // value from the client
},
serialize(value) {
return value.getTime(); // value sent to the client
},
}),
};
scalar Date
type MyType {
created: Date
}
ENUMS
![](https://media1.tenor.com/images/8cfee6f33f4ee52418ba49c6d609c82e/tenor.gif?itemid=14125435)
# Enum of allowed countries:
enum AllowedCountry {
Germany
USA
Sweden
Denmark
}
type Passenger {
name: String!
age: Int!
country: AllowedCountry!
#Country accepts only one of the values from the enum
}
Schema - Circular Reference
![](https://i.pinimg.com/originals/0b/66/57/0b6657dd6ce17b447e8277db4bed206e.gif)
type Passenger {
name: String!
location: Location!
}
type Location {
country: String!
passenger: Passenger!
}
query getPassenger {
name
location {
counrty
passenger {
name
location {
country
passenger {
name
location {
country
}
}
}
}
}
}
Backup - graphql-depth-limit
Massive data in response
![](https://media.giphy.com/media/lck0qwKrqD7VrI2Qw2/200.gif)
type Passenger {
name: String!
age: Int!
}
type Query {
getAllPassenger: [Passenger!]!
}
type Passenger {
name: String!
age: Int!
}
type Query {
getAllPassenger(limit: Int): [Passenger!]!
}
type Passenger {
name: String!
age: Int!
}
type Query {
# a limit of 10 makes sure, when a limit is not passed,
# it doesnt send more than 10 values
getAllPassenger(limit: Int = 10): [Passenger!]!
}
![](https://i.gifer.com/BeG4.gif)
thank you
QA Time:
@vilvaathibanpb
![](https://p10cdn4static.sharpschool.com/UserFiles/Servers/Server_208743/Image/twitter2.png)
follow me on twitter
Please drop in some suggestions and feedback, so I can get better next time
GraphQL: Anti Patterns in Schema design
By Vilva Athiban
GraphQL: Anti Patterns in Schema design
- 556