简体   繁体   中英

How to do POST partial updates via REST API and using DDD?

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.

  • retrieve domain data
  • compare existing domain data with data provided in request body (develop comparison logic)
  • decide which behavior(s) to trigger
  • trigger selected behavior(s)
  • if behavior is valid, persist entire (updated) domain data

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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM