SlideShare a Scribd company logo
1 of 30
Pragmatic API
Design
Jeremy Buisson
FULL-STACKTECHTALKS|CRITEOLABS|05-03-2020
@jbuisson
@jbuiss0n
FULL-STACKTECHTALKS|CRITEOLABS|05-03-2020
Using
Dungeons & Dragons
@jbuisson
@jbuiss0n
Jeremy Buisson
Let's create a API
Not another standard
Let's create a API
Not another standard
Developers common-sense
Let's create a API
Not another standard
Developers common-sense
Key principles
Let's create a
Character
Name
Abilities
Races
Classes
Hitpoints, Experience, Level, Proficiency
Character creation
POST /api/characters
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"name": "Herumor the Ferocious",
"class": "Paladin",
"race": "MountainDwarf"
}
{
"id": 1,
"name": "Herumor the Ferocious",
"race": "MountainDwarf",
"class": "Paladin",
"strength": { "value": 16, "modifier": 3 },
"dexterity": { "value": 11, "modifier": 0 },
"constitution": { "value": 16, "modifier": 3 },
"intelligence": { "value": 9, "modifier": -1 },
"wisdom": { "value": 10, "modifier": 0 },
"charisma": { "value": 16, "modifier": 3 },
"armorClass": 11,
"experience": 0,
"level": 1,
"proficiency": 2,
"hitPoints": 13
}
Character update
PATCH /api/characters/1
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"name": "Herumor the not so Ferocious
}
{
"id": 1,
"name": "Herumor the not so Ferocious",
"race": "MountainDwarf",
"class": "Paladin",
"strength": { "value": 16, "modifier": 3 },
"dexterity": { "value": 11, "modifier": 0 },
"constitution": { "value": 16, "modifier": 3 },
"intelligence": { "value": 9, "modifier": -1 },
"wisdom": { "value": 10, "modifier": 0 },
"charisma": { "value": 16, "modifier": 3 },
"armorClass": 11,
"experience": 0,
"level": 1,
"proficiency": 2,
"hitPoints": 13
}
More advanced
use-cases
ATTACK
HIT
Character Action
Attack
POST /api/characters/1/attack
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"roll": 6,
"isCritical": false,
"isFumble": true
}
Character Action
GET /api/characters/2
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"id": 2,
"name": "Aegwinthiuran of the Never Ending Bloody Winter",
"race": "HighElf",
"class": "Wizard",
"strength": { "value": 7, "modifier": -2 },
"dexterity": { "value": 14, "modifier": 2 },
"constitution": { "value": 14, "modifier": 2 },
"intelligence": { "value": 18, "modifier": 4 },
"wisdom": { "value": 12, "modifier": 1 },
"charisma": { "value": 10, "modifier": 0 },
"armorClass": 12,
"experience": 0,
"level": 1,
"proficiency": 2,
"hitPoints": 8
}
Character Action
POST /api/characters/2/hit
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"type": "Slashing",
"roll": "1d8+3"
}
{
"damage": 3,
"isDead": false
}
Using the Flame Tongue
Using the Flame Tongue
{
"type": "Slashing",
"roll": "1d8+3"
}
{
"type": "Fire",
"roll": "2d6"
}
Batch Actions
POST /api/characters/2/hit/_batch
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
[
{
"type": "Slashing",
"roll": "1d8+3"
},
{
"type": "Fire",
"roll": "2d6"
}
]
[
{
"damage": 3,
"isDead": false
},
{
"damage": 4,
"isDead": false
}
]
Casting a Fireball
Casting a Fireball
{
"type": "Fire",
"roll": "8d6"
}
{
"ability": "Dexterity",
"difficulty": 16
}
Character Action
POST /api/characters/1/save
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"ability": "Dexterity",
"difficulty": 16
}
{
"success": true,
"isCritical": false,
"isFumble": false
}
Nested Actions
POST /api/characters/1/hit
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"type": "Fire",
"roll": "8d6",
"save": {
"ability": "Dexterity",
"difficulty": 16
}
}
{
"damage": 12,
"isDead": false,
"save": {
"success": true,
"isCritical": false,
"isFumble": false
}
}
Batch Actions
POST /api/characters/_batch/hit
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"characters": [1, 3],
"action": {
"type": "Fire",
"roll": "8d6",
"save": {
"ability": "Dexterity",
"difficulty": 16
}
}
}
{
"1": {
"damage": 12,
"isDead": false,
"save": {
"success": true,
"isCritical": false,
"isFumble": false
}
},
"3": {
"damage": 24,
"isDead": true,
"save": {
"success": false,
"isCritical": false,
"isFumble": true
}
}
}
Batch Actions
POST /api/characters/1/_batch
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"hit": {
"type": "Fire",
"roll": "8d6",
"save": {
"ability": "Dexterity",
"difficulty": 16
}
},
"save": {
"ability": "Constitution",
"difficulty": 10
}
}
{
"hit": {
"damage": 12,
"isDead": false,
"save": {
"success": true,
"isCritical": false,
"isFumble": false
}
},
"save": {
"success": true,
"isCritical": false,
"isFumble": false
}
}
Batch Actions
POST /api/characters/_batch
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
{
"1": {
"hit": {
"type": "Fire", "roll": "8d6",
"save": { "ability": "Dexterity", "difficulty": 16 }
},
"save": { "ability": "Constitution", "difficulty": 10 }
},
"3": {
"hit": {
"type": "Fire", "roll": "4d6",
"save": { "ability": "Dexterity", "difficulty": 16 }
}
}
}
{
"1": {
"hit": {
"damage": 12,
"isDead": false,
"save": {
"success": true,
"isCritical": false,
"isFumble": false
}
},
"save": {
"success": true,
"isCritical": false,
"isFumble": false
}
},
"3": {
"hit": {
"damage": 17,
"isDead": true,
"save": {
"success": false,
"isCritical": false,
"isFumble": true
}
}
}
}
Search
??? /api/characters/???
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
???
[
{
"id": 1,
"name": "Herumor the Ferocious",
"race": "MountainDwarf",
"class": "Paladin",
...
"proficiency": 2,
"hitPoints": 13
},
{
"id": 2,
"name": "Aegwinthiuran of the Never Ending Bloody Winter",
"race": "HighElf",
"class": "Wizard",
...
"proficiency": 2,
"hitPoints": 8
},
...
]
Search
GET /api/characters
? dexterity >= 18
& intelligence > 10
& name ~= Mysterious
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
[
{
"id": 4,
"name": "Hurgal the Mysterious",
"race": "Drow",
"class": "Ranger",
...
"armorClass": 14,
"experience": 0,
"level": 1,
"proficiency": 2,
"hitPoints": 13
},
]
GET /api/characters/count
? dexterity >= 18
& intelligence > 10
& name ~= Mysterious
HOST: https://dnd.jbuisson.fr
Content-Type: application/json
1
@jbuisson
@jbuiss0n
Roll for initiative !
Question ?
Jeremy Buisson

More Related Content

Similar to Pragmatic API Design: Using D&D

AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptIngvar Stepanyan
 
Agile Testing Days 2018 - API Fundamentals - postman collection
Agile Testing Days 2018 - API Fundamentals - postman collectionAgile Testing Days 2018 - API Fundamentals - postman collection
Agile Testing Days 2018 - API Fundamentals - postman collectionJoEllen Carter
 
GraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoGraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoMarcinStachniuk
 
xAPI Camp-Four Lines of Code
xAPI Camp-Four Lines of CodexAPI Camp-Four Lines of Code
xAPI Camp-Four Lines of CodeAnthony Altieri
 
Specification-Driven Development of REST APIs by Alexander Zinchuk
Specification-Driven Development of REST APIs by Alexander Zinchuk   Specification-Driven Development of REST APIs by Alexander Zinchuk
Specification-Driven Development of REST APIs by Alexander Zinchuk OdessaJS Conf
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampAlexei Gorobets
 
Apache AVRO (Boston HUG, Jan 19, 2010)
Apache AVRO (Boston HUG, Jan 19, 2010)Apache AVRO (Boston HUG, Jan 19, 2010)
Apache AVRO (Boston HUG, Jan 19, 2010)Cloudera, Inc.
 
GraphQL IN Golang
GraphQL IN GolangGraphQL IN Golang
GraphQL IN GolangBo-Yi Wu
 
David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...
David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...
David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...Codemotion
 
Cdm mil-18 - hypermedia ap is for headless platforms and data integration
Cdm mil-18 - hypermedia ap is for headless platforms and data integrationCdm mil-18 - hypermedia ap is for headless platforms and data integration
Cdm mil-18 - hypermedia ap is for headless platforms and data integrationDavid Gómez García
 
AWS CloudFormation Session
AWS CloudFormation SessionAWS CloudFormation Session
AWS CloudFormation SessionKamal Maiti
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functionsYan Cui
 
NoSQL & MongoDB
NoSQL & MongoDBNoSQL & MongoDB
NoSQL & MongoDBShuai Liu
 
Hypermedia APIs - GeekOut
Hypermedia APIs - GeekOutHypermedia APIs - GeekOut
Hypermedia APIs - GeekOutJan Kronquist
 
Working with the Web: 
Decoding JSON
Working with the Web: 
Decoding JSONWorking with the Web: 
Decoding JSON
Working with the Web: 
Decoding JSONSV.CO
 
Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009Heiko Behrens
 

Similar to Pragmatic API Design: Using D&D (20)

AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript
 
Agile Testing Days 2018 - API Fundamentals - postman collection
Agile Testing Days 2018 - API Fundamentals - postman collectionAgile Testing Days 2018 - API Fundamentals - postman collection
Agile Testing Days 2018 - API Fundamentals - postman collection
 
JavaScript Neednt Hurt - JavaBin talk
JavaScript Neednt Hurt - JavaBin talkJavaScript Neednt Hurt - JavaBin talk
JavaScript Neednt Hurt - JavaBin talk
 
ElasticSearch Hands On
ElasticSearch Hands OnElasticSearch Hands On
ElasticSearch Hands On
 
GraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoGraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za mało
 
xAPI Camp-Four Lines of Code
xAPI Camp-Four Lines of CodexAPI Camp-Four Lines of Code
xAPI Camp-Four Lines of Code
 
Response2
Response2Response2
Response2
 
Specification-Driven Development of REST APIs by Alexander Zinchuk
Specification-Driven Development of REST APIs by Alexander Zinchuk   Specification-Driven Development of REST APIs by Alexander Zinchuk
Specification-Driven Development of REST APIs by Alexander Zinchuk
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
 
Drupal Mobile
Drupal MobileDrupal Mobile
Drupal Mobile
 
Apache AVRO (Boston HUG, Jan 19, 2010)
Apache AVRO (Boston HUG, Jan 19, 2010)Apache AVRO (Boston HUG, Jan 19, 2010)
Apache AVRO (Boston HUG, Jan 19, 2010)
 
GraphQL IN Golang
GraphQL IN GolangGraphQL IN Golang
GraphQL IN Golang
 
David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...
David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...
David Gómez G. - Hypermedia APIs for headless platforms and Data Integration ...
 
Cdm mil-18 - hypermedia ap is for headless platforms and data integration
Cdm mil-18 - hypermedia ap is for headless platforms and data integrationCdm mil-18 - hypermedia ap is for headless platforms and data integration
Cdm mil-18 - hypermedia ap is for headless platforms and data integration
 
AWS CloudFormation Session
AWS CloudFormation SessionAWS CloudFormation Session
AWS CloudFormation Session
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
 
NoSQL & MongoDB
NoSQL & MongoDBNoSQL & MongoDB
NoSQL & MongoDB
 
Hypermedia APIs - GeekOut
Hypermedia APIs - GeekOutHypermedia APIs - GeekOut
Hypermedia APIs - GeekOut
 
Working with the Web: 
Decoding JSON
Working with the Web: 
Decoding JSONWorking with the Web: 
Decoding JSON
Working with the Web: 
Decoding JSON
 
Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009Building DSLs with Xtext - Eclipse Modeling Day 2009
Building DSLs with Xtext - Eclipse Modeling Day 2009
 

Recently uploaded

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
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
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
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
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
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
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
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
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 

Recently uploaded (20)

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
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
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
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
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
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
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 

Pragmatic API Design: Using D&D

  • 3. Let's create a API Not another standard
  • 4. Let's create a API Not another standard Developers common-sense
  • 5. Let's create a API Not another standard Developers common-sense Key principles
  • 7. Character creation POST /api/characters HOST: https://dnd.jbuisson.fr Content-Type: application/json { "name": "Herumor the Ferocious", "class": "Paladin", "race": "MountainDwarf" } { "id": 1, "name": "Herumor the Ferocious", "race": "MountainDwarf", "class": "Paladin", "strength": { "value": 16, "modifier": 3 }, "dexterity": { "value": 11, "modifier": 0 }, "constitution": { "value": 16, "modifier": 3 }, "intelligence": { "value": 9, "modifier": -1 }, "wisdom": { "value": 10, "modifier": 0 }, "charisma": { "value": 16, "modifier": 3 }, "armorClass": 11, "experience": 0, "level": 1, "proficiency": 2, "hitPoints": 13 }
  • 8. Character update PATCH /api/characters/1 HOST: https://dnd.jbuisson.fr Content-Type: application/json { "name": "Herumor the not so Ferocious } { "id": 1, "name": "Herumor the not so Ferocious", "race": "MountainDwarf", "class": "Paladin", "strength": { "value": 16, "modifier": 3 }, "dexterity": { "value": 11, "modifier": 0 }, "constitution": { "value": 16, "modifier": 3 }, "intelligence": { "value": 9, "modifier": -1 }, "wisdom": { "value": 10, "modifier": 0 }, "charisma": { "value": 16, "modifier": 3 }, "armorClass": 11, "experience": 0, "level": 1, "proficiency": 2, "hitPoints": 13 }
  • 10.
  • 11.
  • 12.
  • 13.
  • 14. Character Action Attack POST /api/characters/1/attack HOST: https://dnd.jbuisson.fr Content-Type: application/json { "roll": 6, "isCritical": false, "isFumble": true }
  • 15. Character Action GET /api/characters/2 HOST: https://dnd.jbuisson.fr Content-Type: application/json { "id": 2, "name": "Aegwinthiuran of the Never Ending Bloody Winter", "race": "HighElf", "class": "Wizard", "strength": { "value": 7, "modifier": -2 }, "dexterity": { "value": 14, "modifier": 2 }, "constitution": { "value": 14, "modifier": 2 }, "intelligence": { "value": 18, "modifier": 4 }, "wisdom": { "value": 12, "modifier": 1 }, "charisma": { "value": 10, "modifier": 0 }, "armorClass": 12, "experience": 0, "level": 1, "proficiency": 2, "hitPoints": 8 }
  • 16. Character Action POST /api/characters/2/hit HOST: https://dnd.jbuisson.fr Content-Type: application/json { "type": "Slashing", "roll": "1d8+3" } { "damage": 3, "isDead": false }
  • 17. Using the Flame Tongue
  • 18. Using the Flame Tongue { "type": "Slashing", "roll": "1d8+3" } { "type": "Fire", "roll": "2d6" }
  • 19. Batch Actions POST /api/characters/2/hit/_batch HOST: https://dnd.jbuisson.fr Content-Type: application/json [ { "type": "Slashing", "roll": "1d8+3" }, { "type": "Fire", "roll": "2d6" } ] [ { "damage": 3, "isDead": false }, { "damage": 4, "isDead": false } ]
  • 21. Casting a Fireball { "type": "Fire", "roll": "8d6" } { "ability": "Dexterity", "difficulty": 16 }
  • 22. Character Action POST /api/characters/1/save HOST: https://dnd.jbuisson.fr Content-Type: application/json { "ability": "Dexterity", "difficulty": 16 } { "success": true, "isCritical": false, "isFumble": false }
  • 23. Nested Actions POST /api/characters/1/hit HOST: https://dnd.jbuisson.fr Content-Type: application/json { "type": "Fire", "roll": "8d6", "save": { "ability": "Dexterity", "difficulty": 16 } } { "damage": 12, "isDead": false, "save": { "success": true, "isCritical": false, "isFumble": false } }
  • 24. Batch Actions POST /api/characters/_batch/hit HOST: https://dnd.jbuisson.fr Content-Type: application/json { "characters": [1, 3], "action": { "type": "Fire", "roll": "8d6", "save": { "ability": "Dexterity", "difficulty": 16 } } } { "1": { "damage": 12, "isDead": false, "save": { "success": true, "isCritical": false, "isFumble": false } }, "3": { "damage": 24, "isDead": true, "save": { "success": false, "isCritical": false, "isFumble": true } } }
  • 25. Batch Actions POST /api/characters/1/_batch HOST: https://dnd.jbuisson.fr Content-Type: application/json { "hit": { "type": "Fire", "roll": "8d6", "save": { "ability": "Dexterity", "difficulty": 16 } }, "save": { "ability": "Constitution", "difficulty": 10 } } { "hit": { "damage": 12, "isDead": false, "save": { "success": true, "isCritical": false, "isFumble": false } }, "save": { "success": true, "isCritical": false, "isFumble": false } }
  • 26.
  • 27. Batch Actions POST /api/characters/_batch HOST: https://dnd.jbuisson.fr Content-Type: application/json { "1": { "hit": { "type": "Fire", "roll": "8d6", "save": { "ability": "Dexterity", "difficulty": 16 } }, "save": { "ability": "Constitution", "difficulty": 10 } }, "3": { "hit": { "type": "Fire", "roll": "4d6", "save": { "ability": "Dexterity", "difficulty": 16 } } } } { "1": { "hit": { "damage": 12, "isDead": false, "save": { "success": true, "isCritical": false, "isFumble": false } }, "save": { "success": true, "isCritical": false, "isFumble": false } }, "3": { "hit": { "damage": 17, "isDead": true, "save": { "success": false, "isCritical": false, "isFumble": true } } } }
  • 28. Search ??? /api/characters/??? HOST: https://dnd.jbuisson.fr Content-Type: application/json ??? [ { "id": 1, "name": "Herumor the Ferocious", "race": "MountainDwarf", "class": "Paladin", ... "proficiency": 2, "hitPoints": 13 }, { "id": 2, "name": "Aegwinthiuran of the Never Ending Bloody Winter", "race": "HighElf", "class": "Wizard", ... "proficiency": 2, "hitPoints": 8 }, ... ]
  • 29. Search GET /api/characters ? dexterity >= 18 & intelligence > 10 & name ~= Mysterious HOST: https://dnd.jbuisson.fr Content-Type: application/json [ { "id": 4, "name": "Hurgal the Mysterious", "race": "Drow", "class": "Ranger", ... "armorClass": 14, "experience": 0, "level": 1, "proficiency": 2, "hitPoints": 13 }, ] GET /api/characters/count ? dexterity >= 18 & intelligence > 10 & name ~= Mysterious HOST: https://dnd.jbuisson.fr Content-Type: application/json 1
  • 30. @jbuisson @jbuiss0n Roll for initiative ! Question ? Jeremy Buisson

Editor's Notes

  1. Hello everyone I'm Jeremy, lead of the WebApps Engineering team, here at Criteo, also leading the effort around our Marketing API, or MAPI if you're more intimate with it. I wanted to talk with you about Pragmatic API Design, but that was actually an excuse to secure few minutes here and now to talk about Dungeons & Dragons !
  2. Who here know and have already played Dungeons & Dragons, or any kind of role playing game, like Vampire, Chtulu, Warhammer, ... For all the others, WHAT ARE YOU WAITING FOR? Come on, as you've seen there people here that could introduce you to the game. And if you're too shy, come see me after, I'd be glad to do it for you. As there is a lot of people here, let's create an API so we can all play together, and don't wait for everyone to take their turn.
  3. So what do I mean by pragmatic API? Don't be scared, it's **NOT** another standard, like Restfull, Hateos, GraphQL, ... because standard are generic by definition, created to cover as much uses-cases as possible, and could often make you build complex design to achieve simple things.
  4. With Pragmatic here, I mean designing an API using our developers common sense, to create the best API possible for our specific purpose, which is in this case playing D&D. This mean we'll allow us to not follow standard, **when it make sense of course** -being pragmatic we don't want to reinvent the wheel.
  5. Finally our key principles: - **Affordance**: This is actually not a true english word, but I like it **"Affordance"**. It the ability of something to suggest its usage, being auto-descriptive and self-explanatory. - **KISS**: Keep It Simple Stupid. Anyone should be able to use you API wihtout having to refer to extended documentation, **swagger must be enougth**. We're are developpers, we all do that: not looking at the documentation, and complaining if we can't understand what's happening. This is why I keep building Ikea furniture upside-down (true story, people here can relate). - **Client centric**: Like Criteo, be client centric. Do not build the API for your data nor services. Do it for your consumers, by putting yourselves in their shoes. - **Avoid Ambiguity**: Never allow your consumers, your clients, to do one thing with more than one way. Use standard, concrete and shared terms. Not specific business terms nor acronyms. This is what we'll do now by playing D&D and stop talking about boring API design.
  6. The first thing you need to play D&D is to create your own character. Of course you can choose your name, using up to 50 letters. If you don't know why so many, you've never meet an Elvish player, and there fancy names... There is some randomness, using Dice that you should roll to determine your abilities: Strength, Dexterity, Consitution, Intelligence, Wisdom and Charisma. For those who wonder what's the difference between Intelligence and Wisdom: "Intelligence is knowing the Tomatoes is a fruit, Wisdom is knowing you don't put Tomatoes in a fruit salad". (Checked, I always dreamed to say that in front of many people: life achievement here). Anyway, I do not trust my players to roll any dice, especially during character creation. So the dice rolls should be behind our API. And for simplicity, we'll not allow to distribute results amongst abilities, we'll go for full randomness. You need to choose a race (from the Dwarf, Elf, Halfling, Human, ...) and a class (Barbarian, Paladin, Rogue, Ranger, Warlock or Wizard).
  7. And here is how it works using our API. A basic POST request to our *characters* endpoints. And it will return the fully created character. So, ok our Mountain Dwarf Paladin isn't that Ferocious actually, let's rename him. But we don't want to be able to update everything, as I say I don't trust my players, change there experience, etc...
  8. So the only thing we should allow is to PATCH our name for now. And of course we should return the exact same result as a creation, a fully operational character. Ok we've done the easy thing now, let's do more advanced and fun thing with our Paladin.
  9. Usually when you play D&D, you'll very quickly found yourself fighting some ugly monsters like Kobolds, Goblins or Skeletons, or if there's a Rogue in your party, smashing the Rogue for trying to steal your money. To attack it's simple you Roll a D20, add you Strength ability modifier (or dexterity) depending on the weapon you're using, add you're Proficiency (if your character knows how to use its weapon). If the result is more or equal  than the **ArmorClass** of your target, it's a sucess. In any case, if the dice give you a 1, it's a fumble an automatic failure and depending on you Game Master, it could end very badly, like actually hitting by mistake you're friendly wizard, who doesn't have a lot of hitpoints... But if the dice gave you a natural 20, then it's a critical an automatic success, allowing you to double your damage. But don't worry, the Game Master always find a way to take his revenge. If you successfuly attacked, then you can hit the target, roll your weapon's damage, add your Strength (or Dexterity) and finally lower the target hitpoints. But how do we do all of that ?
  10. Client computation: no this is no more a simple tu use API, this will require extended works. We do not want to be Ikea.
  11. Consequences: do we implement triggers? Reminds me too much of old SQL project. And anyway it isn't self explanatory anymore. We want to be explicit about what happens here.
  12. Do we create new resources then, like we should with the REST approach ? Do we really want to persist them, to generate identifiers, is there any update to handle? When is it actually processed ? Ok too many question, we're failing to design something simple, something **PRAGMATIC**. Let's take a deep breath, and get back to D&D. What are we trying to do? We're trying to take an **ACTION**!
  13. You will POST an action, which is not a resource, but an entity on its own. This action, will give you an outcome (or nothing if there is no result except success/failure). This nice thing is even if it's not a resource, we cans still nest action if we want. And finally it's very easy to bacth actions, when they are explicitly designed. Let's try it
  14. This one is very easy; it doesn't need a body to be executed. We could of course create one with the weapon we want to use, ... but let's say we'll use the weapon currently equiped, so we can go grab some foods sooner. Our action have an outcome, a bit disapointed here, as we've rolled a fumble... even if we have 6 in total thanks to our strength and proficiency (remember, D20 + strength modifier + proficiency).
  15. So fine, let's actually hit our friendly wizard, wich is an elf as you can see by his name. We can retreive hime easyli as usual using a GET resource if you know its Id. We can see he only have 8 hitpoints unfortunately for him. But anyway let's hit him.
  16. Let's say our ferocious paladin have a Longsword equiped in his main hand. Longsword does 1d8 + his strength modifier,  of slashing damage. This is a basic action, using an HTTP POST against the wizard, fortunalty for him, it seems the wizard had already cast the spell **Blade Ward**, giving him resistance to the attack, so we only hit hime for 3 damage.
  17. But our Paladin is Ferocious, so let's say he actually have the magic weapon: Flame Tongue! This weapon is awesome, not only it looks badass to have a flaming weapon, but it also add 2d6 fire damage, which could overcome the wizard resistance.
  18. In terms of API it should be 2 different hit action then, that we should execute as a **BATCH**.
  19. So let's actually batch the action, but explicitly, by addin the explicit keyword "_batch". The underscore is important here, to make the difference between resources, actions and keywords. It's nomenclature, starting with the underscore make it clear as sonn as you see it, that it's not an action nor a new resource, nor an the id of a resources. And in terms of usage, it's simple too, just, add all you batch actions in an array, and receive an array of outcomes. For each action, it's index ni the array is the key to find the corresponding outcome. Ok our Wizard is not dead, and is all out for revenge...
  20. This is the usual wizard signature spell, and it's no joke: "A bright streak flashes from your pointing finger to an area you choose and then blossoms with a low roar into an explosion of flame." There may be a bit of excalation betweend our Paladin and Wizard here... "Each hit creature must make a Dexterity saving throw. Taking 8d6 fire damage on a failed save, or half as much damage on a successful one."
  21. So we have a new kind of action here, the **Saving Throw**. It’s a test against one of your abilities. Very often you'll have to do this kind of action, to resist spell damage, or avoid being poisons, deceased...
  22. So we have a new action, with its own outcome, once again pretty simple and explicit.
  23. And so we can directly use it as part of the Hit action, as an optionnal **Nested** action, giving you the nested outcome. Here we succeeded the save, and only suffer half of the rolled damage that was by then 24. Fine, but actually... a fireball hits **EVERYONE** in the area, including our deer rogue, who was obviously trying to steal money from our Paladin.
  24. To do that we’ll continue to use our batch keyword, but this time, in place of the id of the targeted characters. Then we can have a CharactersBatchAction, that encapsulate the action itself, and defined the ids of the character on which we want to execute the action. That way can damage ou Paladin very badly even if he succeeded his saving throw. And as exepcted in this kind of scenario, our Rogue fumble his save, and died.
  25. The batch weyword, can also allow us to execute in one batch different actions at the same time, here with the Hit action from the fireball, and a Constitution saving throw, because the explosion also broke some flask of poison the rogue have in its bag.
  26. We can do even more batching !
  27. Here, only the Paladin is doing the Constitution saving throw, because the Rogue is immune to its own poison. Also the rogue have a special feat, allowing him to reduce incomming damage from things like a fireball, so he only suffer 4d6 fire damage. (He’s dead anyway) Time to look out for a new character, let’s search from all the characters…
  28. But how do we do search ? Do we post an action to the collection? Do we create a new SEARCH resource ? What’s would be it’s boyd anyway? But we know we want to return the list characters, exactly like we do on the characters endpoint. Do we really want to build a search? Or do we actually want to add filters to the characters list ?!
  29. Well the query string looks perfect for that ! We can even count using this way. It require a little bit of work ou the API side, but that’s not actually that complex, to do. In fact, some of you may have been sneaky enough to find out already, but the API is exists and is available at the URL dnd.jbuisson.fr. The code is also fully available on gitlab, at gitlab.com/jbuisson/dnd https://dnd.jbuisson.fr/api/characters?intelligence%3C18&intelligence%3E10&Name~=Mysterious
  30. https://gitlab.com/jbuisson/dnd