Granularity and structure of commands when updating an aggregate?

150 views
Skip to first unread message

Daniel Compton

unread,
Aug 22, 2017, 1:32:45 AM8/22/17
to DDD/CQRS
Hi folks

We are working on a CQRS (no event sourcing) system which is organised around documents (workspaces). Each document can have a number of collaborators. Users can add, remove, and update collaborators. We are looking at creating commands for updating collaborators on a workspace. We've found these options options for what the client sends to the server:

1. A very coarse grained "UpdateWorkspace" command with the entire updated workspace. This doesn't have much precision or value after the fact, and requires a lot of work on the server to figure out what changed. It also doesn't capture the intent of the business action very well.
2. An "UpdateCollaborators" command which provides the new list of collaborators. The server then diffs the current collaborators in the database with the new provided ones to work out what action to take. This takes more work, and also raises concurrency issues if multiple people send UpdateCollaborators commands at the same time.
3. An "UpdateCollaborators" command which provides a map of operations, e.g. `{:added ... :deleted ... :modified}`. The server doesn't have to infer what work is required, as the client tells it.
4.The client sends a batch of more specific commands when the "Save" button is clicked, e.g. "AddCollaborator", "UpdateCollaboratorEmailAddress", "RemoveCollaborator". This is more work for the client to keep track of which commands to send, and to effectively deduplicate commands, e.g. UpdateCollaboratorEmailAddress followed by RemoveCollaborator should just end up as RemoveCollaborator (probably?).
5. After every field modification, send a single command like "UpdateCollaboratorEmailAddress". This makes it much less likely that concurrent update errors will occur, but probably requires more optimistic updating work so that the user isn't waiting for a response after changing each field.

We are leaning away from 5 based on the UI work that optimistic updates would require, and 2, 3, and 4 all have merits. What are people's recommendations, and experience with writing commands to update an aggregate, and structuring the data inside that command?

Thanks, Daniel.

Rickard Öberg

unread,
Aug 22, 2017, 3:08:31 AM8/22/17
to ddd...@googlegroups.com
Hi Daniel!

I have a very similar situation, and here's what we did.

We have individual commands for adding/removing things, and in cases
where bulk updates are needed we support uploading CSV files to our
REST API, which goes through the file one line at a time and figures
out what to do (user missing->add, user existing->update), and then
issues the regular commands as if they were done one by one. In one
case we have an automated process figure out the list of items in a
collection and issues that as a single command/event, and then the
read model is updated by removing everything from the collection and
adding whatever was listed in the event, in order. From a concurrency
point of view we view it as "last one wins", as it is a very very rare
thing to happen in our case.

/Rickard
> --
> You received this message because you are subscribed to the Google Groups
> "DDD/CQRS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to dddcqrs+u...@googlegroups.com.
> Visit this group at https://groups.google.com/group/dddcqrs.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages