Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
Commanding a More
Meaningful REST API
Brandon Mueller
@fatmuemoo
fatmuemoo.com
Panhandle Web Tech
http://www.meetup.com/Panhandle-Web-Tech/
6:30 on the Third Tuesday of the Month
@ Firebrand Media
229 ...
What is covered
● API Basics
● API Good Practices
● CRUD API Examples
● Commanding API Explained
● Commanding API Examples...
What is NOT covered
● Security or Authentication
● HAL or HATEOAS
● CQRS* or DDD*
● Nitty-Gritty Implementation Details
● The farm is a home to people, places and things. These
are the nouns in your API
● Nouns are also called resources or en...
HTTP verb Resource URL Explanation
POST /barns Creates a new barn
GET /barns Gets all the barns on
the farm
GET /barns/11 ...
Some Good Ideas to Follow:
1. ALWAYS use plural nouns - keeps it simple
2. Nest resources!
/barns/30/animals
/barns/30/sta...
Read The Spec
Status Codes: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Headers: http://www.w3.org/Protocols/rf...
Status Codes In a Nutshell
● 2xx - It worked
● 3xx - Go away
● 4xx - The client messed up
● 5xx - The server messed up
Idempotent/Safe Methods
Idempotent methods can be applied over and
over again and always have the same effect on
the resou...
Idempotent/Safe Methods
Method Idempotent Safe
GET YES YES
POST NO NO
PUT YES NO
DELETE YES NO
PATCH NO NO
HEAD YES YES
OP...
POST v PUT v PATCH
● POST is used to create an entity
● PUT is used to update an entity where you
must send the entire rep...
CRUDy Workflow
Client
Application Server
Client uses HTTP POST, GET, PUT and DELETE
Verbs to CREATE, READ, UPDATE and DELE...
Create an Animal
$.post({
url: '/api/animals,
data: {
name: 'Bob',
}
});
Server returns “201 created” status and a
JSON re...
Read Animals
$.get({
url: '/api/animals,
});
Server returns “200 OK”, and a JSON
representation of the streets
{
page: 1,
...
Update an Animal
$.put({
url: '/api/animals/30',
data: {
name: 'Robert'
}
});
Server returns “200 OK” status and a
JSON re...
Delete an Animal
$.ajax({
type: 'DELETE',
url: '/api/animals/30'
});
Server returns a ‘204 No Content’
status and should n...
Awesome!
● We can create some really awesome APIs
where we can create, read, update, and
delete entities in a standard way...
Where is the Business Logic?
Client
Application Server
Client uses HTTP POST, GET, PUT and DELETE
Verbs to CREATE, READ, U...
Business Logic on The Client Side?
● A CRUD API is a really good way to expose
meaningful data in a flexible way
● You mak...
Really? Client Side?
● Stopping at CRUD functionality limits what
your API can actually do
● Complex business problems sho...
Wait, This SUCKS!
How do you go beyond simply creating,
reading, updating, and deleting things?
● How do you reroof a barn...
Commanding API
Take a resources, add a command (verb) to the
end, send data for that command in POST
HTTP verb
○ POST /bar...
Command or Resource?
Command Resource
Verb Noun
You can only POST and
sometimes GET never PUT or
DELETE
All HTTP verbs are...
HTTP
Verb
Command URL Explained
POST /barns/11/reroof Sends the command to reroof
barn 11
GET /barns/11/reroof Meta data a...
Commands Are NOT First Class Citizens
POST /createBarn
POST /barns
POST /updateBarn
PUT /barns/1
POST /cleanBarn
POST /bar...
Example: Reroof a barn
$.post({
url: '/barns/11/reroof'
});
Server responds with ‘200 OK’ status, and meta
data about the ...
Wait: That’s Not The Whole Story
We use a Commanding Pattern because we
are performing an action on a resource. In the
rea...
Reroof a Barn
$.post({
url: '/barns/11/reroof'
});
Server responds with ‘202 Accepted’
status, and meta data about the
com...
Reroof a Barn; Check Status
$.get({
url: '/barns/11/reroof/123e4567-e89b-12d3-a456-426655440000'
});
Server responds with ...
Client
Application Server
Client sends
POST command
Clients Checks
Status URL until
complete, updating
UI with progress
What About Querying?
● Sometimes a query request cannot be
completed in a reasonable amount of time
● Sometimes you have t...
Querying
$.post({
url: '/chickens/search'
data: {
type: 'heritage'
egg_color: 'blue',
age: 'young'
}
}); Just like a comma...
Getting Results...
If you try to hit the results link before the results are
complete:
● the server will return the search...
Getting Results...
HTTP Request
Do we have
the
resource?
203 With a Retry
After Header
And Status URL
200 OK
Has the data
...
Separating Command and
Queries...
Developing expressive and
meaningful endpoints...
Using nouns and verbs that
reflect wha...
ENTERING
BUZZWORD ZONE!
CQRS Martin Fowler
CQRS stands for Command Query Responsibility
Segregation. It's a pattern that I first heard described b...
DDD Wikipedia
Domain-driven design (DDD) is an approach to software
development for complex needs by connecting the
implem...
DDD and CQRS in My Own Words...
● Domain Driven Design is a philosophy and methodology
in which your domain model should r...
DDD - Know Your Role!
● Talk to stakeholders and domain
experts
● Strive for a ubiquitous language
● Know the context in w...
CRUD API Commanding API
Create a Product POST /products POST /products
Update a Product PUT /products/{id} PUT /products/{...
CQRS and CRUD, Mutually
Exclusive?
Commands Are NOT First Class Citizens
POST /createBarn
POST /barns
POST /updateBarn
PUT /barns/1
POST /cleanBarn
POST /bar...
CQRS and CRUD Can Coexist
PUT or PATCH is just an update command BUT:
● Be very selective with what is allowed to be updat...
Brandon Mueller
@fatmuemoo
fatmuemoo.com
END
BUZZWORDS
Próxima SlideShare
Cargando en…5
×

Cqrs api v2

3.922 visualizaciones

Publicado el

Publicado en: Tecnología
  • @neverfox Slides are explicit about the fact you may GET the Command resource to get the progress/final state of the Command execution. A Command is not necessarily fire-and-forget. It's up to the client deciding whether forgetting after firing
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí
  • I like this API design, but it assumes there is a way for the API server to find out, on demand, things like command status and optimistic views of the changed aggregate. That means there is state related to the submission of a command. The slides don't address how you maintain that state and it's not accounted for in the usual discussions of the CQRS/ES pattern. There's usually nothing to query about the progress (or lack thereof); it's talked about as fire-and-forget. So how would you address this such that this API would actually work as intended?
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí

Cqrs api v2

  1. 1. Commanding a More Meaningful REST API Brandon Mueller @fatmuemoo fatmuemoo.com
  2. 2. Panhandle Web Tech http://www.meetup.com/Panhandle-Web-Tech/ 6:30 on the Third Tuesday of the Month @ Firebrand Media 229 East Martin St, Suite 5 Martinsburg, WV 25401
  3. 3. What is covered ● API Basics ● API Good Practices ● CRUD API Examples ● Commanding API Explained ● Commanding API Examples ● CRUD and Commanding Coexistence
  4. 4. What is NOT covered ● Security or Authentication ● HAL or HATEOAS ● CQRS* or DDD* ● Nitty-Gritty Implementation Details
  5. 5. ● The farm is a home to people, places and things. These are the nouns in your API ● Nouns are also called resources or entities. ● The nouns are represented in your API by the URL. ● Like things inside of your farm, you can do things with your resources. ● You tell your nouns to do things via verbs. ● The HTTP spec come with built in verbs, among these are GET, PUT, POST, and DELETE ● These verbs are great for CRUD functionality. Your API is Like a Farm
  6. 6. HTTP verb Resource URL Explanation POST /barns Creates a new barn GET /barns Gets all the barns on the farm GET /barns/11 Gets the barn with the ID of 11 PUT /barns/11 Updates the barn with the ID of 11 DELETE /barns/11 Deletes the barn with the ID of 11 C R U D
  7. 7. Some Good Ideas to Follow: 1. ALWAYS use plural nouns - keeps it simple 2. Nest resources! /barns/30/animals /barns/30/stables/1/animals 3. Handle errors with a standardized response body 4. Use the standard HTTP verbs 5. Use appropriate HTTP headers 6. Use appropriate HTTP response codes
  8. 8. Read The Spec Status Codes: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html Headers: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
  9. 9. Status Codes In a Nutshell ● 2xx - It worked ● 3xx - Go away ● 4xx - The client messed up ● 5xx - The server messed up
  10. 10. Idempotent/Safe Methods Idempotent methods can be applied over and over again and always have the same effect on the resource Safe methods do not have any modifying effect on the resource
  11. 11. Idempotent/Safe Methods Method Idempotent Safe GET YES YES POST NO NO PUT YES NO DELETE YES NO PATCH NO NO HEAD YES YES OPTIONS YES YES
  12. 12. POST v PUT v PATCH ● POST is used to create an entity ● PUT is used to update an entity where you must send the entire representation of the entity as you wish for it to be stored ● PATCH is used to update an entity where you send only the fields that need updated
  13. 13. CRUDy Workflow Client Application Server Client uses HTTP POST, GET, PUT and DELETE Verbs to CREATE, READ, UPDATE and DELETE
  14. 14. Create an Animal $.post({ url: '/api/animals, data: { name: 'Bob', } }); Server returns “201 created” status and a JSON representation of the newly created street, as well a link to the street { id: 30, name: 'Bob', _links: { self: '/api/animals/30' } }
  15. 15. Read Animals $.get({ url: '/api/animals, }); Server returns “200 OK”, and a JSON representation of the streets { page: 1, total_pages: 10, items: [ {id: 30, 'name': 'Bob', _links: { self: '/api/animals/30' }, .... ] }
  16. 16. Update an Animal $.put({ url: '/api/animals/30', data: { name: 'Robert' } }); Server returns “200 OK” status and a JSON representation of the street, { id: 30, name: 'Robert', _links: { self: '/api/animals/30' } } NOTE: Most implementations of the PUT verb require the entire representation of the entity. See HTTP PATCH verb for updating with a partial representation of the entity.
  17. 17. Delete an Animal $.ajax({ type: 'DELETE', url: '/api/animals/30' }); Server returns a ‘204 No Content’ status and should not have a response body. Any further GET requests to /api/animals/30 should return a ‘404 Not Found’ status
  18. 18. Awesome! ● We can create some really awesome APIs where we can create, read, update, and delete entities in a standard way. ● These standards have lead to some very powerful libraries that can help you create and consume CRUD APIs
  19. 19. Where is the Business Logic? Client Application Server Client uses HTTP POST, GET, PUT and DELETE Verbs to CREATE, READ, UPDATE and DELETE ● Sometimes this is what we want ● When we create APIs we don’t always know the specific use case ● We just want to expose the data
  20. 20. Business Logic on The Client Side? ● A CRUD API is a really good way to expose meaningful data in a flexible way ● You make few assumptions on how the data will be displayed or used ● Fosters innovation and allows for really interesting clients
  21. 21. Really? Client Side? ● Stopping at CRUD functionality limits what your API can actually do ● Complex business problems should not rely on client side implementations ● Only implementing CRUD functionality can lead to an API that doesn't know what it does, it only knows about the data it stores
  22. 22. Wait, This SUCKS! How do you go beyond simply creating, reading, updating, and deleting things? ● How do you reroof a barn? ● Clean a stable? ● Castrate a goat?
  23. 23. Commanding API Take a resources, add a command (verb) to the end, send data for that command in POST HTTP verb ○ POST /barns/11/reroof ○ POST /barns/1/stable/2/clean ○ POST /goats/133/castrate
  24. 24. Command or Resource? Command Resource Verb Noun You can only POST and sometimes GET never PUT or DELETE All HTTP verbs are OK Once a command has been submitted, it cannot be removed or updated (read only) Most resources can be removed or updated
  25. 25. HTTP Verb Command URL Explained POST /barns/11/reroof Sends the command to reroof barn 11 GET /barns/11/reroof Meta data about reroof command and barn 11. Maybe the last time it was reroofed, whether or not we are currently reroofing GET /barns/11/reroof/{cmdID} Meta data about the specific instance of the reroof command
  26. 26. Commands Are NOT First Class Citizens POST /createBarn POST /barns POST /updateBarn PUT /barns/1 POST /cleanBarn POST /barns/1/clean
  27. 27. Example: Reroof a barn $.post({ url: '/barns/11/reroof' }); Server responds with ‘200 OK’ status, and meta data about the command: {cmd_id: '123e4567-e89b-12d3-a456-426655440000'} In this example, the command is executed and completed within the lifecycle of the HTTP request.
  28. 28. Wait: That’s Not The Whole Story We use a Commanding Pattern because we are performing an action on a resource. In the real word, these actions can take time.
  29. 29. Reroof a Barn $.post({ url: '/barns/11/reroof' }); Server responds with ‘202 Accepted’ status, and meta data about the command: { cmd_id: '123e4567-e89b-12d3-a456-426655440000', _links: { status: '/barns/11/reroof/123e4567-e89b-12d3-a456-426655440000' } }
  30. 30. Reroof a Barn; Check Status $.get({ url: '/barns/11/reroof/123e4567-e89b-12d3-a456-426655440000' }); Server responds with ‘200 OK’ status and data about the command { shingles_complete: 5, out_of: 1024, }
  31. 31. Client Application Server Client sends POST command Clients Checks Status URL until complete, updating UI with progress
  32. 32. What About Querying? ● Sometimes a query request cannot be completed in a reasonable amount of time ● Sometimes you have to send a POST payload in order to send enough data for the server to process a query ● This is a special case of a command
  33. 33. Querying $.post({ url: '/chickens/search' data: { type: 'heritage' egg_color: 'blue', age: 'young' } }); Just like a command, we return ‘202 Accepted’ status, and return some meta data: { cmd_id: '7ecba660-5032-11e4-916c-0800200c9a66', _links: { results: '/chickens/searchResults/7ecba660-5032-11e4-916c-0800200c9a66', status: '/chickens/search/7ecba660-5032-11e4-916c-0800200c9a66', } }
  34. 34. Getting Results... If you try to hit the results link before the results are complete: ● the server will return the search results in whatever state it is available ● return a ‘203 Non-Authoritative Information’ ● a link to the status url ● and a Retry-After header Using this pattern, you can expire content and return the 203 status code to tell the client to refresh the content
  35. 35. Getting Results... HTTP Request Do we have the resource? 203 With a Retry After Header And Status URL 200 OK Has the data expired or still being created? Check Status Status Is it done?
  36. 36. Separating Command and Queries... Developing expressive and meaningful endpoints... Using nouns and verbs that reflect what your API actually does... Proudly Inspired by Others
  37. 37. ENTERING BUZZWORD ZONE!
  38. 38. CQRS Martin Fowler CQRS stands for Command Query Responsibility Segregation. It's a pattern that I first heard described by Greg Young. At its heart is a simple notion that you can use a different model to update information than the model you use to read information. This simple notion leads to some profound consequences for the design of information systems. http://martinfowler.com/bliki/CQRS.html
  39. 39. DDD Wikipedia Domain-driven design (DDD) is an approach to software development for complex needs by connecting the implementation to an evolving model. The premise of domain-driven design is the following: 1. Placing the project's primary focus on the core domain and domain logic. 2. Basing complex designs on a model of the domain. 3. Initiating a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses particular domain problems. http://en.wikipedia.org/wiki/Domain-driven_design
  40. 40. DDD and CQRS in My Own Words... ● Domain Driven Design is a philosophy and methodology in which your domain model should represent the business problems that your app is actually solving ● Command Query Responsibility Segregation is the strategy of separating commands from queries, as opposed to CRUD functionality which is represented in the same object. CQRS can help you follow the SOLID principle
  41. 41. DDD - Know Your Role! ● Talk to stakeholders and domain experts ● Strive for a ubiquitous language ● Know the context in which your API endpoints will be used ● Use this knowledge to develop your endpoints
  42. 42. CRUD API Commanding API Create a Product POST /products POST /products Update a Product PUT /products/{id} PUT /products/{id} Mark Product as Active PUT /products/{id} POST /products/{id}/activate Describe a Product PUT /products/{id} POST /products/{id}/describe Order a Product ???? POST /products/{id}/order Markdown a Product PUT /products/{id} POST /products/{id}/markdown Review a products POST /products/{id}/reviews POST /products/{id}/review Mark product as out of stock PUT /products/{id} POST /products/{id}/outOfStock CRUDy v Commandy
  43. 43. CQRS and CRUD, Mutually Exclusive?
  44. 44. Commands Are NOT First Class Citizens POST /createBarn POST /barns POST /updateBarn PUT /barns/1 POST /cleanBarn POST /barns/1/clean
  45. 45. CQRS and CRUD Can Coexist PUT or PATCH is just an update command BUT: ● Be very selective with what is allowed to be updated ● It is not always appropriate to expose update functionality for a particular object or property ● If another command updates a property, updating that property directly probably shouldn’t be allowed DELETE is a special use case command too
  46. 46. Brandon Mueller @fatmuemoo fatmuemoo.com END BUZZWORDS

×