Rest API and DDD
Solution 1:
I have read many articles about the REST on the internet.
Based on what I see here, you really need to watch at least one of Jim Webber's talks on REST and DDD
- Rest in Practice
- Domain Driven Design for RESTful Systems
But what to do with the rest of the use cases?
Ignore the API for a moment - how would you do it with HTML forms?
You'd presumably have a web page the presents a representation of Deal
, with a bunch of links on it. One link would take you to the HoldDeal
form, and another link would take you to the ChangePrice
form, and so on. Each of those forms would have zero or more fields to fill in, and the forms would each post to some resource to update the domain model.
Would they all post to the same resource? Perhaps, perhaps not. They would all have the same media type, so if they were all posting to the same web endpoint, you would have to decode the content on the other side.
Given that approach, how do you implement your system? Well, the media type wants to be json, based on your examples, but there really isn't anything wrong with the rest of it.
1) Use verbs:
That's fine.
But! Verbs can not be used in the url(in REST theory).
Um... no. REST doesn't care about the spelling of your resource identifiers. There's a bunch of URI best practices that claim that verbs are bad - that's true - but that's not something that follows from REST.
But if people are being so fussy, you name the endpoint for the command instead of the verb. (ie: "hold" isn't a verb, it's a use case).
Use 1 PUT request for all operations:
Honestly, that one isn't bad either. You won't want to share the URI though (because of the way the PUT method is specified), but use a template where the clients can specify a unique identifier.
Here's the meat: you are building an API on top of HTTP and HTTP methods. HTTP is designed for document transfer. The client gives you a document, describing a requested change in your domain model, and you apply the change to the domain (or not), and return another document describing the new state.
Borrowing from the CQRS vocabulary for a moment, you are posting commands to update your domain model.
PUT /commands/{commandId}
{
'deal' : dealId
'action': 'HoldDeal',
'params': {'reason': 'test'}
}
Justification - you are putting a specific command (a command with a specific Id) into the command queue, which is a collection.
PUT /rest/{version}/deals/{dealId}/commands/{commandId}
{
'action': 'HoldDeal',
'params': {'reason': 'test'}
}
Yeah, that's fine too.
Take another look at RESTBucks. It's a coffee shop protocol, but all of the api is just passing small documents around to advance the state machine.
Solution 2:
Design your rest api independently of the domain layer.
One of the key concepts of domain driven design is low coupling between your different software layers. So, when you design your rest api, you think about the best rest api you could have. Then, it's the role of the application layer to call the domain objects to perform the required use case.
I can't design your rest api for you, because I don't know what you're trying to do, but here are some ideas.
As I understand it, you have a Deal resource. As you said, creation/deletion are easy :
- POST /rest/{version}/deals
- DELETE /rest/{version}/deals/{id}.
Then, you want to "hold" a deal. I don't know what that means, you have to think about what it changes in the resource "Deal". Does it change an attribute? if yes, then you're simply modifying the Deal resource.
PUT /rest/{version}/deals/{id}
{
...
held: true,
holdReason: "something",
...
}
Does it add something? Can you have several holds on a Deal? Sounds to me that "hold" is a noun. If it's ugly, find a better noun.
POST /rest/{version}/deals/{id}/holds
{
reason: "something"
}
another solution: forget REST theory. If you think your api would be clearer, more efficient, simpler with the use of verbs in the url, then by all means, do it. You can probably find a way to avoid it, but if you can't, don't do something ugly just because it's the norm.
Look at twitter's api: lots of developers say that twitter has a well designed API. Tadaa, it uses verbs! Who cares, as long as it's cool and easy to use?
I can't design your api for you, you're the only one who knows your use cases, but i'll say again my two advices:
- Design the rest api by itself, and then use the application layer to call the appropriate domain objects in the right order. That's exactly what the application layer is here for.
- Don't follow the norms and theories blindly. Yes, you should try to follow good practices and norms as much as possible, but if you can't then leave them behind (after careful consideration of course)