SlideShare a Scribd company logo
1 of 62
Download to read offline
@eamodeorubio@eamodeorubio
DOOMEDDOOMED TOTO
µServiceµService
MONOLITH HEAVENMONOLITH HEAVEN
SHARED OWNERSHIP?SHARED OWNERSHIP?
TOO MANY FEATURESTOO MANY FEATURES
(ANYONE HEARD ABOUT SRP?)(ANYONE HEARD ABOUT SRP?)
LET'S BREAK THE MONOLITHLET'S BREAK THE MONOLITH
(A.K.A(A.K.A µServiceµServiceS)S)
µServicesµServices === DISTRIBUTED MONOLITH?=== DISTRIBUTED MONOLITH?
WE NEEDWE NEED CONTRACTSCONTRACTS !!!!!!
CONTRACTS WITHCONTRACTS WITH
GraphQLGraphQL
CONTRACTS EVERYWHERECONTRACTS EVERYWHERE
WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT?
DATA MODELDATA MODEL
message PersonalInfo {
required string name;
optional string email;
}
message Employee {
required number employeeId;
required PersonalInfo info;
}
WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT?
DATA OVER THE NETWORKDATA OVER THE NETWORK
{
"employeeId": 33,
"info": {
"name": "John",
"email": null
}
}
WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT?
OPERATIONSOPERATIONS
service EmployeeService {
rpc hire(PersonalInfo) returns (Employee);
}
WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT?
OPERATIONS OVER THE NETWORKOPERATIONS OVER THE NETWORK
POST /employee/rpc HTTP/1.1
Host: example.org
Authorization: Bearer AbCdEf123456
Content-Type: application/json; charset=utf-8
{
"op": "hire",
"args": [{
"name": "John",
"email": null
}]
}
WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT?
OPERATIONS OVER THE NETWORKOPERATIONS OVER THE NETWORK
HTTP/1.1 200 OK
Date: Sun, 10 Oct 2010 23:26:07 GMT
Server: Apache/2.2.8 (Ubuntu) mod_ssl/2.2.8 OpenSSL/0.9.8g
Last-Modified: Sun, 26 Sep 2010 22:04:35 GMT
ETag: "45b6-834-49130cc1182c0"
Content-Type: application/json; charset=utf-8
{
"employeeId": 33,
"info": {
"name": "John",
"email": null
}
}
WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT?
INPUT/OUTPUT INVARIANTSINPUT/OUTPUT INVARIANTS
findById(id: string): Employee -> If
found, we expect the result to have the same id as
specified
updateName(id: string, name:
string): Employee -> If successful, we expect
the returned employee to have the supplied name
SO WHAT HASSO WHAT HAS GraphQLGraphQL TO DOTO DO
WITH CONTRACTS?WITH CONTRACTS?
GraphQLGraphQL DOES DEFINE ADOES DEFINE A
CONTRACT!CONTRACT!
GRAPHQL DOESGRAPHQL DOES NOTNOT MANDATEMANDATE
HOW TO SERIALISE DATAHOW TO SERIALISE DATA
BUT GIVES A JSON SERIALISATIONBUT GIVES A JSON SERIALISATION
RECOMMENDATIONRECOMMENDATION
https://facebook.github.io/graphql/June2018/#sec-
Serialization-Format
GRAPHQL DOESGRAPHQL DOES NOTNOT DEFINEDEFINE
HOW TO TRANSPORT IT OVERHOW TO TRANSPORT IT OVER
THE NETWORKTHE NETWORK
BUT THERE IS ABUT THERE IS A DE FACTODE FACTO STANDARDSTANDARD
Single endpoint: /graphql
Use GET and POST ignoring their semantics
Use application/json and JSON serialisation
4xx for validation and security errors
200 for anything else (partial success)
https://graphql.org/learn/serving-over-http/
SDLSDL
DATA MODELSDATA MODELS
scalar ProductRef
scalar Rating
enum ReviewStatus {
PENDING
ACCEPTED
REJECTED
}
type ProductReview {
id: ID!
productRef: ProductRef!
rating: Rating!
commentary: String
status: ReviewStatus!
}
SDLSDL
QUERIES & MUTATIONSQUERIES & MUTATIONS
input ReviewData {
productRef: ProductId!
rating: Rating!
commentary: String
}
type Query {
productReview(id: ReviewId!): ProductReview
}
type Mutation {
postReview(review: ReviewData!): ProductReview!
deleteReview(id: ReviewId!): boolean
}
QUERY LANGUAGEQUERY LANGUAGE
query {
review1: productReview(id: "1") {
...interestingFields
}
review2: productReview(id: "2") {
...interestingFields
}
review3: productReview(id: "3") {
...interestingFields
}
}
fragment interestingFields on ProductReview {
productRef
rating
}
ERRORS & PARTIAL FAILURESERRORS & PARTIAL FAILURES
{
"data": {
"review1": null,
"review2": {
"productRef": "urn:ishop:product:2",
"rating": 4
},
"review3": null
},
"errors": [
{
"message": "Unexpected DB Error",
"locations": [ { "line": 2, "column": 3 } ],
"path": [ "review1" ]
}
]
}
GraphQLGraphQL + CONVENTIONS = CONTRACT?+ CONVENTIONS = CONTRACT?
SDL
for extra details like errors
De facto standard:
De facto standard:
GraphQL spec
GraphQL over HTTP
GraphQL serialised as JSON
TESTINGTESTING GraphQLGraphQL
CONTRACTSCONTRACTS
WE SHOULD TEST ... WHATWE SHOULD TEST ... WHAT
EXACTLY?EXACTLY?
NOTNOT A CONTRACT TESTA CONTRACT TEST
Correct implementation of business logic
In the server
In the clients
The full end to end behaviour
BOTH SIDES ADHERE TO THE CONTRACTBOTH SIDES ADHERE TO THE CONTRACT
Valid means it complies with the contract
Clients:
Perform valid requests
Can process any valid results
Servers:
Accept valid requests
Always return a valid result
TESTING THE CLIENT SIDETESTING THE CLIENT SIDE
TESTING THE SERVER SIDETESTING THE SERVER SIDE
PROBLEMSPROBLEMS
Tons of boilerplate
Prone to have bugs
Test needs to be kept in sync
Not DRY !!
GraphQLGraphQL TO THE RESCUE!TO THE RESCUE!
Strong Typed SDL give us automation
Test data generators
Mock Servers
Test scenarios scaffolding
No need to test type validation on the server
CONSIDER THIS SDLCONSIDER THIS SDL
scalar ProductRef
scalar Rating
enum ReviewStatus {
PENDING
ACCEPTED
REJECTED
}
type ProductReview {
id: ID!
productRef: ProductRef!
rating: Rating!
commentary: String
status: ReviewStatus!
}
GENERATING TYPES & SCAFFOLDINGGENERATING TYPES & SCAFFOLDING
For example with GraphQLGen
type ID = string
type ProductRef = string
type Rating = number
enum ReviewStatus {
'PENDING',
'ACCEPTED',
'REJECTED'
}
type ProductReview = {
id: ID
productRef: ProductRef
rating: Rating
commentary: string | null
status: ReviewStatus
}
FAKE DATA FOR TESTSFAKE DATA FOR TESTS
A MAINTENANCE BURDENA MAINTENANCE BURDEN
[
{
"id": "2f4dc6ba-bd25-4e66-b369-43a13e0cf150",
"productRef": "urn:ishop:product:2c497439-7802-4cd5-8fb6-f7fa679c
"rating": 4,
"commentary": null,
"status": "PENDING"
},
{
"id": "a9af522d-0d62-46f3-8c1d-71eff807fcc7",
"productRef": "urn:ishop:product:bb509f54-e20f-4fbb-8df7-adeb7b83
"rating": 2,
"commentary": "Vel et rerum nostrum quia. Dolorum fuga nobis sit
"status": "ACCEPTED"
}
]
FAKE DATA GENERATORSFAKE DATA GENERATORS
CUSTOM SCALARSCUSTOM SCALARS
import * as casual from 'casual'
const someID = (): ID => casual.uuid
const someProductRef = (): ProductRef =>
`urn:ishop:product:${someID()}`
const someRating = (): Rating => casual.integer(1, 5)
FAKE DATA GENERATORFAKE DATA GENERATOR
ENUMS & STRINGSENUMS & STRINGS
import * as casual from 'casual'
const someReviewStatus =
() => casual.random_value(ReviewStatus)
type StringTypes =
'title' | 'text' | 'description' | 'string'
const someString = (
{ kind = 'string' }: { kind?: StringTypes } = {}
): string => casual[kind]
FAKE DATA GENERATORFAKE DATA GENERATOR
OBJECT TYPESOBJECT TYPES
import * as casual from 'casual'
const someProductReview =
(options: Partial<ProductReview> = {}) => ({
id: someID(),
productRef: someProductRef(),
rating: someRating(),
commentary: casual.boolean ?
someString({ kind: 'description'}) :
null,
status: someReviewStatus(),
...options
})
FAKE DATA GENERATOR GENERATORSFAKE DATA GENERATOR GENERATORS
REMOVING BOILERPLATEREMOVING BOILERPLATE
Most of the code of the generators are highly regular
Only custom scalars need to be defined
And some minor customisations
FAKE DATA GENERATOR GENERATORSFAKE DATA GENERATOR GENERATORS
REMOVING BOILERPLATEREMOVING BOILERPLATE
// Not (yet) a real library
import { load, nullable, someString } from 'gql-faker'
const myFaker = load('../schemas/reviews.graphql')
myFaker.customScalars({
someID: (): ID => casual.uuid,
someProductRef: (): ProductRef =>
`urn:ishop:product:${myFaker.someID()}`,
someRating: (): Rating => casual.integer(0, 5)
})
myFaker.customiseObject('ProductReview', {
commentary: nullable(
() => someString({
kind: 'description'
})
)
})
CONSIDER THESE OPERATIONSCONSIDER THESE OPERATIONS
input ReviewData {
productRef: ProductId!
rating: Rating!
commentary: String
}
type Query {
productReview(id: ReviewId!): ProductReview
}
type Mutation {
postReview(review: ReviewData!): ProductReview!
deleteReview(id: ReviewId!): boolean
}
TEST SCENARIOS GENERATORTEST SCENARIOS GENERATOR
myFaker.testScenarios({
Query: {
// productReview(id: ReviewId!): ProductReview
productReview: [
{
name: 'found',
result: (id) => someProductReview({ id })
},
{
name: 'not found',
result: null
}
]
}
})
TEST SCENARIOS DEFINITIONTEST SCENARIOS DEFINITION
myFaker.testScenarios({
Mutation: {
// postReview(review: ReviewData!): ProductReview!
postReview: [
{
name: 'with a commentary',
input: () => someReviewData({ commentary: someString() }),
result: (data) => someProductReview({ ...data })
},
{
name: 'without a commentary',
input: () => someReviewData({ commentary: null }),
result: (data) => someProductReview({ ...data })
},
{
name: 'failure',
result: (data) => alreadyExistsError(data.id)
}
]
}
})
TEST SCENARIOS DEFINITIONTEST SCENARIOS DEFINITION
WHAT ABOUTWHAT ABOUT deleteReviewdeleteReview??
// No invariants
// Return value is just a boolean
// Test scenario can be automatically inferred
myFaker.testScenarios({
Mutation: {
// deleteReview(id: ReviewId!): boolean
deleteReview: [
{ name: 'returns true', result: true },
{ name: 'returns false', result: false },
{ name: 'failure', result: () => someSystemError() }
]
}
})
NO BOILERPLATENO BOILERPLATE
ONLY NEED TO DEFINE WHAT ISONLY NEED TO DEFINE WHAT IS NOTNOT IN THE SDLIN THE SDL
Custom Scalars
Domain customisation for Objects and Inputs
Invariants inputs/outputs
Errors (not in SDL)
Edge cases
AUTOMATE!!!AUTOMATE!!!
AUTOMATE!!!AUTOMATE!!!
AUTOMATE!!!AUTOMATE!!!
THETHE EVERGREENEVERGREEN
CONTRACTCONTRACT
CONTRACT DRIFT PROBLEMCONTRACT DRIFT PROBLEM
1. Provider change contract
2. Consumer is not aware of the change
3. Mock server is not updated
4. False passing tests
5. Bug!
USEUSE EVERGREENEVERGREEN CONTRACTS TO AVOIDCONTRACTS TO AVOID
CONTRACT DRIFTCONTRACT DRIFT
DON'TDON'T SEMVERSEMVER
Only contract version in production is relevant
Fix clients ASAP
Save money, don't maintain several versions at the
same time
EVERGREENEVERGREEN
Deprecate and notify
Measure usage of deprecated operations & types
Drop them when usage is low enough
Contract changed? -> Run contract tests for all
services consuming that contract
NEEDNEED SERVICE DIRECTORYSERVICE DIRECTORY TO KNOW FORTO KNOW FOR
WHICH SERVICES THEIR CONTRACTWHICH SERVICES THEIR CONTRACT
TESTS NEED TO BE RUNTESTS NEED TO BE RUN
SERVICE DIRECTORYSERVICE DIRECTORY
Unique source of truth regarding Contracts
Keeps tracks of:
Which services provide which Contracts
Which services consume which contracts
Contracts = SDL + Test Scenario Definitions
Well known test cases
SERVICE DESCRIPTORSERVICE DESCRIPTOR
Each service repo contains a descriptor
Provided contracts definitions
Reference to all consumed contracts
ENFORCINGENFORCING EVERGREENEVERGREEN CONTRACTSCONTRACTS
On commit push -> push descriptor to service
directory
On broken contract test -> notify directory
On deprecated usage -> notify directory
During CI
In production (telemetry)
SERVICE DIRECTORYSERVICE DIRECTORY
HUMANS!HUMANS!
Search & consult the contracts and their test cases
Report service dependencies
Report services with broken contract tests (provider
& consumer)
Report services using deprecated contract features

More Related Content

Similar to Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018

Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and ToolsBob Paulin
 
Marvel of Annotation Preprocessing in Java by Alexey Buzdin
Marvel of Annotation Preprocessing in Java by Alexey BuzdinMarvel of Annotation Preprocessing in Java by Alexey Buzdin
Marvel of Annotation Preprocessing in Java by Alexey BuzdinJava User Group Latvia
 
Post Sharp Talk
Post Sharp TalkPost Sharp Talk
Post Sharp Talkwillmation
 
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) ExtensionSimplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) ExtensionVMware Tanzu
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava SchmidtJavaDayUA
 
Types End-to-End @ samsara
Types End-to-End @ samsaraTypes End-to-End @ samsara
Types End-to-End @ samsaraStephen Wan
 
How to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational DatabaseHow to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational DatabaseDATAVERSITY
 
Agile data presentation 3 - cambridge
Agile data   presentation 3 - cambridgeAgile data   presentation 3 - cambridge
Agile data presentation 3 - cambridgeRomans Malinovskis
 
Groovy Architectural Flexibility
Groovy Architectural FlexibilityGroovy Architectural Flexibility
Groovy Architectural FlexibilityDavid Dawson
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java DevelopersYakov Fain
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Elixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.jsElixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.jsJeroen Visser
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)James Titcumb
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)James Titcumb
 
Test First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in GrailsTest First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in GrailsTim Berglund
 
Embedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaEmbedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaJevgeni Kabanov
 
Domain Driven Design Tactical Patterns
Domain Driven Design Tactical PatternsDomain Driven Design Tactical Patterns
Domain Driven Design Tactical PatternsRobert Alexe
 
Test First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTest First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTim Berglund
 

Similar to Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018 (20)

Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
 
Marvel of Annotation Preprocessing in Java by Alexey Buzdin
Marvel of Annotation Preprocessing in Java by Alexey BuzdinMarvel of Annotation Preprocessing in Java by Alexey Buzdin
Marvel of Annotation Preprocessing in Java by Alexey Buzdin
 
Post Sharp Talk
Post Sharp TalkPost Sharp Talk
Post Sharp Talk
 
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) ExtensionSimplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
 
Postman On Steroids
Postman On SteroidsPostman On Steroids
Postman On Steroids
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava Schmidt
 
Structure on a freeform world
Structure on a freeform worldStructure on a freeform world
Structure on a freeform world
 
Types End-to-End @ samsara
Types End-to-End @ samsaraTypes End-to-End @ samsara
Types End-to-End @ samsara
 
How to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational DatabaseHow to Handle NoSQL with a Relational Database
How to Handle NoSQL with a Relational Database
 
Agile data presentation 3 - cambridge
Agile data   presentation 3 - cambridgeAgile data   presentation 3 - cambridge
Agile data presentation 3 - cambridge
 
Groovy Architectural Flexibility
Groovy Architectural FlexibilityGroovy Architectural Flexibility
Groovy Architectural Flexibility
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Elixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.jsElixir, GraphQL and Vue.js
Elixir, GraphQL and Vue.js
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)
 
Test First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in GrailsTest First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in Grails
 
Embedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaEmbedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for Java
 
Domain Driven Design Tactical Patterns
Domain Driven Design Tactical PatternsDomain Driven Design Tactical Patterns
Domain Driven Design Tactical Patterns
 
Test First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTest First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in Grails
 

More from Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyCodemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaCodemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserCodemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 - Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Codemotion
 

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 

Recently uploaded (20)

AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 

Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018

  • 1.
  • 6. TOO MANY FEATURESTOO MANY FEATURES (ANYONE HEARD ABOUT SRP?)(ANYONE HEARD ABOUT SRP?)
  • 7. LET'S BREAK THE MONOLITHLET'S BREAK THE MONOLITH (A.K.A(A.K.A µServiceµServiceS)S)
  • 8. µServicesµServices === DISTRIBUTED MONOLITH?=== DISTRIBUTED MONOLITH?
  • 9. WE NEEDWE NEED CONTRACTSCONTRACTS !!!!!!
  • 12. WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT? DATA MODELDATA MODEL message PersonalInfo { required string name; optional string email; } message Employee { required number employeeId; required PersonalInfo info; }
  • 13. WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT? DATA OVER THE NETWORKDATA OVER THE NETWORK { "employeeId": 33, "info": { "name": "John", "email": null } }
  • 14. WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT? OPERATIONSOPERATIONS service EmployeeService { rpc hire(PersonalInfo) returns (Employee); }
  • 15. WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT? OPERATIONS OVER THE NETWORKOPERATIONS OVER THE NETWORK POST /employee/rpc HTTP/1.1 Host: example.org Authorization: Bearer AbCdEf123456 Content-Type: application/json; charset=utf-8 { "op": "hire", "args": [{ "name": "John", "email": null }] }
  • 16. WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT? OPERATIONS OVER THE NETWORKOPERATIONS OVER THE NETWORK HTTP/1.1 200 OK Date: Sun, 10 Oct 2010 23:26:07 GMT Server: Apache/2.2.8 (Ubuntu) mod_ssl/2.2.8 OpenSSL/0.9.8g Last-Modified: Sun, 26 Sep 2010 22:04:35 GMT ETag: "45b6-834-49130cc1182c0" Content-Type: application/json; charset=utf-8 { "employeeId": 33, "info": { "name": "John", "email": null } }
  • 17. WHAT'S INSIDE A CONTRACT?WHAT'S INSIDE A CONTRACT? INPUT/OUTPUT INVARIANTSINPUT/OUTPUT INVARIANTS findById(id: string): Employee -> If found, we expect the result to have the same id as specified updateName(id: string, name: string): Employee -> If successful, we expect the returned employee to have the supplied name
  • 18. SO WHAT HASSO WHAT HAS GraphQLGraphQL TO DOTO DO WITH CONTRACTS?WITH CONTRACTS?
  • 19. GraphQLGraphQL DOES DEFINE ADOES DEFINE A CONTRACT!CONTRACT!
  • 20. GRAPHQL DOESGRAPHQL DOES NOTNOT MANDATEMANDATE HOW TO SERIALISE DATAHOW TO SERIALISE DATA
  • 21. BUT GIVES A JSON SERIALISATIONBUT GIVES A JSON SERIALISATION RECOMMENDATIONRECOMMENDATION https://facebook.github.io/graphql/June2018/#sec- Serialization-Format
  • 22. GRAPHQL DOESGRAPHQL DOES NOTNOT DEFINEDEFINE HOW TO TRANSPORT IT OVERHOW TO TRANSPORT IT OVER THE NETWORKTHE NETWORK
  • 23. BUT THERE IS ABUT THERE IS A DE FACTODE FACTO STANDARDSTANDARD Single endpoint: /graphql Use GET and POST ignoring their semantics Use application/json and JSON serialisation 4xx for validation and security errors 200 for anything else (partial success) https://graphql.org/learn/serving-over-http/
  • 24. SDLSDL DATA MODELSDATA MODELS scalar ProductRef scalar Rating enum ReviewStatus { PENDING ACCEPTED REJECTED } type ProductReview { id: ID! productRef: ProductRef! rating: Rating! commentary: String status: ReviewStatus! }
  • 25. SDLSDL QUERIES & MUTATIONSQUERIES & MUTATIONS input ReviewData { productRef: ProductId! rating: Rating! commentary: String } type Query { productReview(id: ReviewId!): ProductReview } type Mutation { postReview(review: ReviewData!): ProductReview! deleteReview(id: ReviewId!): boolean }
  • 26. QUERY LANGUAGEQUERY LANGUAGE query { review1: productReview(id: "1") { ...interestingFields } review2: productReview(id: "2") { ...interestingFields } review3: productReview(id: "3") { ...interestingFields } } fragment interestingFields on ProductReview { productRef rating }
  • 27. ERRORS & PARTIAL FAILURESERRORS & PARTIAL FAILURES { "data": { "review1": null, "review2": { "productRef": "urn:ishop:product:2", "rating": 4 }, "review3": null }, "errors": [ { "message": "Unexpected DB Error", "locations": [ { "line": 2, "column": 3 } ], "path": [ "review1" ] } ] }
  • 28. GraphQLGraphQL + CONVENTIONS = CONTRACT?+ CONVENTIONS = CONTRACT? SDL for extra details like errors De facto standard: De facto standard: GraphQL spec GraphQL over HTTP GraphQL serialised as JSON
  • 30. WE SHOULD TEST ... WHATWE SHOULD TEST ... WHAT EXACTLY?EXACTLY?
  • 31. NOTNOT A CONTRACT TESTA CONTRACT TEST Correct implementation of business logic In the server In the clients The full end to end behaviour
  • 32. BOTH SIDES ADHERE TO THE CONTRACTBOTH SIDES ADHERE TO THE CONTRACT Valid means it complies with the contract Clients: Perform valid requests Can process any valid results Servers: Accept valid requests Always return a valid result
  • 33. TESTING THE CLIENT SIDETESTING THE CLIENT SIDE
  • 34. TESTING THE SERVER SIDETESTING THE SERVER SIDE
  • 35. PROBLEMSPROBLEMS Tons of boilerplate Prone to have bugs Test needs to be kept in sync Not DRY !!
  • 36. GraphQLGraphQL TO THE RESCUE!TO THE RESCUE! Strong Typed SDL give us automation Test data generators Mock Servers Test scenarios scaffolding No need to test type validation on the server
  • 37. CONSIDER THIS SDLCONSIDER THIS SDL scalar ProductRef scalar Rating enum ReviewStatus { PENDING ACCEPTED REJECTED } type ProductReview { id: ID! productRef: ProductRef! rating: Rating! commentary: String status: ReviewStatus! }
  • 38. GENERATING TYPES & SCAFFOLDINGGENERATING TYPES & SCAFFOLDING For example with GraphQLGen type ID = string type ProductRef = string type Rating = number enum ReviewStatus { 'PENDING', 'ACCEPTED', 'REJECTED' } type ProductReview = { id: ID productRef: ProductRef rating: Rating commentary: string | null status: ReviewStatus }
  • 39. FAKE DATA FOR TESTSFAKE DATA FOR TESTS A MAINTENANCE BURDENA MAINTENANCE BURDEN [ { "id": "2f4dc6ba-bd25-4e66-b369-43a13e0cf150", "productRef": "urn:ishop:product:2c497439-7802-4cd5-8fb6-f7fa679c "rating": 4, "commentary": null, "status": "PENDING" }, { "id": "a9af522d-0d62-46f3-8c1d-71eff807fcc7", "productRef": "urn:ishop:product:bb509f54-e20f-4fbb-8df7-adeb7b83 "rating": 2, "commentary": "Vel et rerum nostrum quia. Dolorum fuga nobis sit "status": "ACCEPTED" } ]
  • 40. FAKE DATA GENERATORSFAKE DATA GENERATORS CUSTOM SCALARSCUSTOM SCALARS import * as casual from 'casual' const someID = (): ID => casual.uuid const someProductRef = (): ProductRef => `urn:ishop:product:${someID()}` const someRating = (): Rating => casual.integer(1, 5)
  • 41. FAKE DATA GENERATORFAKE DATA GENERATOR ENUMS & STRINGSENUMS & STRINGS import * as casual from 'casual' const someReviewStatus = () => casual.random_value(ReviewStatus) type StringTypes = 'title' | 'text' | 'description' | 'string' const someString = ( { kind = 'string' }: { kind?: StringTypes } = {} ): string => casual[kind]
  • 42. FAKE DATA GENERATORFAKE DATA GENERATOR OBJECT TYPESOBJECT TYPES import * as casual from 'casual' const someProductReview = (options: Partial<ProductReview> = {}) => ({ id: someID(), productRef: someProductRef(), rating: someRating(), commentary: casual.boolean ? someString({ kind: 'description'}) : null, status: someReviewStatus(), ...options })
  • 43. FAKE DATA GENERATOR GENERATORSFAKE DATA GENERATOR GENERATORS REMOVING BOILERPLATEREMOVING BOILERPLATE Most of the code of the generators are highly regular Only custom scalars need to be defined And some minor customisations
  • 44. FAKE DATA GENERATOR GENERATORSFAKE DATA GENERATOR GENERATORS REMOVING BOILERPLATEREMOVING BOILERPLATE // Not (yet) a real library import { load, nullable, someString } from 'gql-faker' const myFaker = load('../schemas/reviews.graphql') myFaker.customScalars({ someID: (): ID => casual.uuid, someProductRef: (): ProductRef => `urn:ishop:product:${myFaker.someID()}`, someRating: (): Rating => casual.integer(0, 5) }) myFaker.customiseObject('ProductReview', { commentary: nullable( () => someString({ kind: 'description' }) ) })
  • 45. CONSIDER THESE OPERATIONSCONSIDER THESE OPERATIONS input ReviewData { productRef: ProductId! rating: Rating! commentary: String } type Query { productReview(id: ReviewId!): ProductReview } type Mutation { postReview(review: ReviewData!): ProductReview! deleteReview(id: ReviewId!): boolean }
  • 46. TEST SCENARIOS GENERATORTEST SCENARIOS GENERATOR myFaker.testScenarios({ Query: { // productReview(id: ReviewId!): ProductReview productReview: [ { name: 'found', result: (id) => someProductReview({ id }) }, { name: 'not found', result: null } ] } })
  • 47. TEST SCENARIOS DEFINITIONTEST SCENARIOS DEFINITION myFaker.testScenarios({ Mutation: { // postReview(review: ReviewData!): ProductReview! postReview: [ { name: 'with a commentary', input: () => someReviewData({ commentary: someString() }), result: (data) => someProductReview({ ...data }) }, { name: 'without a commentary', input: () => someReviewData({ commentary: null }), result: (data) => someProductReview({ ...data }) }, { name: 'failure', result: (data) => alreadyExistsError(data.id) } ] } })
  • 48. TEST SCENARIOS DEFINITIONTEST SCENARIOS DEFINITION WHAT ABOUTWHAT ABOUT deleteReviewdeleteReview?? // No invariants // Return value is just a boolean // Test scenario can be automatically inferred myFaker.testScenarios({ Mutation: { // deleteReview(id: ReviewId!): boolean deleteReview: [ { name: 'returns true', result: true }, { name: 'returns false', result: false }, { name: 'failure', result: () => someSystemError() } ] } })
  • 49. NO BOILERPLATENO BOILERPLATE ONLY NEED TO DEFINE WHAT ISONLY NEED TO DEFINE WHAT IS NOTNOT IN THE SDLIN THE SDL Custom Scalars Domain customisation for Objects and Inputs Invariants inputs/outputs Errors (not in SDL) Edge cases
  • 54. CONTRACT DRIFT PROBLEMCONTRACT DRIFT PROBLEM 1. Provider change contract 2. Consumer is not aware of the change 3. Mock server is not updated 4. False passing tests 5. Bug!
  • 55. USEUSE EVERGREENEVERGREEN CONTRACTS TO AVOIDCONTRACTS TO AVOID CONTRACT DRIFTCONTRACT DRIFT
  • 56. DON'TDON'T SEMVERSEMVER Only contract version in production is relevant Fix clients ASAP Save money, don't maintain several versions at the same time
  • 57. EVERGREENEVERGREEN Deprecate and notify Measure usage of deprecated operations & types Drop them when usage is low enough Contract changed? -> Run contract tests for all services consuming that contract
  • 58. NEEDNEED SERVICE DIRECTORYSERVICE DIRECTORY TO KNOW FORTO KNOW FOR WHICH SERVICES THEIR CONTRACTWHICH SERVICES THEIR CONTRACT TESTS NEED TO BE RUNTESTS NEED TO BE RUN
  • 59. SERVICE DIRECTORYSERVICE DIRECTORY Unique source of truth regarding Contracts Keeps tracks of: Which services provide which Contracts Which services consume which contracts Contracts = SDL + Test Scenario Definitions Well known test cases
  • 60. SERVICE DESCRIPTORSERVICE DESCRIPTOR Each service repo contains a descriptor Provided contracts definitions Reference to all consumed contracts
  • 61. ENFORCINGENFORCING EVERGREENEVERGREEN CONTRACTSCONTRACTS On commit push -> push descriptor to service directory On broken contract test -> notify directory On deprecated usage -> notify directory During CI In production (telemetry)
  • 62. SERVICE DIRECTORYSERVICE DIRECTORY HUMANS!HUMANS! Search & consult the contracts and their test cases Report service dependencies Report services with broken contract tests (provider & consumer) Report services using deprecated contract features