Domain Managed Project for RESTful Systems - Jim Webber
What if I want to provide a way to update an entire ticket atomically?
If you want to update the entire ticket atomically, precise aggregates; aggregates are the wrong tool in your field if what you really want is a repository of key values ββwith CRUD semantics.
Aggregates only make sense when their domain business rules apply. Do not build a tractor when all you need is a shovel.
As an example, a user can make a PUT request for / api / tickets / 5
It will be a mess. In a CRUD implementation, replacing the current state of a resource by sending it a representation of a new state is appropriate. But this is not at all suitable for aggregates in general, because the state of the aggregate is not under the control of you, the client / publisher.
A more suitable idiom is to publish a message on the bus that, when processed by the domain, will have a side effect of achieving the desired changes.
PUT /api/tickets/5/messages/{messageId}
NOW your application service is viewing the message and sending commands to the aggregate
if(DTO.Status != null && dto.Status == "RESOLVED") supportTicket.Resolve(); if(DTO.Title != null) supportTicket.setNewTitle(DTO.title);
This is normal, but in practice it is much more common to make the message explicit about what needs to be done.
{ "messageType" : "ResolveWithNewTitle" , "status" : "RESOLVED" , "Title":"Some crazy title" }
or even...
[ { "messageType" : "ChangeTitle" , "Title" : "Some crazy title" } , { "messageType" : "ResolveTicket" } ]
Basically, you want to provide the application with enough context so that it can perform a real message check.
let's say I had aggregates that encapsulated the necessary business logic, but there was also a new demand for atomic update functions, and I was trying to figure out the best way to handle this.
So, the right way to deal with this is to first deal with it at the domain level - sit down with experts from your domain, make sure that everyone understands this requirement and how to express it in the ubiquitous language, etc.
Implement any new methods that you need in the consolidated root.
After using the use case in the domain correctly, you can start worrying about your resources following the previous pattern - the resource simply accepts the incoming request and invokes the appropriate commands.