Reputation: 7325
I have a project where rest api is being refactored from classic CRUD into domain drive design (DDD). One of the challenges is that endpoints have to remain the same using same verbs and payload.
I have the following situation
For example GET /orders/1048 returns
{
"id":1048,
"order_total":100.11,
"is_paid":true,
"order_status":"active",
"items":[
{
"id":5000,
"name":"baseball hat"
},
{
"id":5001,
"name":"baseball bat"
}
]
}
Now if I have POST order/update/1048 where I send full or partial request model via POST (not via PUT because POST is not idempotent and PUT request entire model to be provided, always) and based on data provided I want to trigger particular domain behavior
a) update status case 1.
{
"id":1048,
"order_total":100.11,
"is_paid":true,
"order_status":"cancel",
"items":[
{
"id":5000,
"name":"baseball hat"
},
{
"id":5001,
"name":"baseball bat"
}
]
}
b) update status case 2.
{
"id": 1048,
"order_status": "cancel"
}
c) update items case
{
"id":1048,
"items":[
{
"id":5000,
"name":"baseball hat"
}
]
}
d) update status + items
{
"id":1048,
"order_status":"cancel",
"items":[
{
"id":5000,
"name":"baseball hat"
}
]
}
My plan is to do the following inside application layer and domain layer.
This is not really "DDD ready request" since I am not sending commands using PATCH, but these is the only workaround I can think of, and I would like to know am I doing it right?
Upvotes: 1
Views: 1613
Reputation: 14064
If content types are changeable, you can use them to convey information about the command and match on that rather than field by field comparison.
PUT /order/1048
Content-Type:application/json;command=UpdateStatus
https://www.infoq.com/articles/rest-api-on-cqrs
As a side note, UpdateStatus is probably not specific enough as a command name.
Upvotes: 2
Reputation: 17683
Considering that you may not or can not modify the client:
My plan is to do the following inside application layer and domain layer
If you do this only in the Application layer then it is DDD as long as the domain layer contains only domain logic. The diff algorithm does not belong in the domain layer, it should belong in a temporary refactoring facade; this facade could be put even farther, in front of the Application layer in order to be removed simpler after the refactoring is complete.
If/when you refactor the client:
The commands that you send to the domain (to the Aggregates) can be wrapped in RESTful requests using POST or PUT (depending on the idempotency of your commands). For every domain command (not for every domain entity) you can have a REST resource, like http://server/place/order/{orderId}
.
Then you can drop that refactoring facade.
Upvotes: 2