Let's say i have an application structured around the basics of CQRS event sourcing:
- App dispatch Commands DTOs that are handled by Command Handlers
- Aggregate raise events when Command's datas are passed and applied
- Event Handler apply domain logic and side effects when they receive events they are interested to (in my case: they do projections).
My question is: in the steps 1 and 3, do we need to give all informations in Command and Event DTOs, or can we pass ID of some entities that handlers can then fetch from database ?
Example:
- I have a Employee Aggregate
- A RegisterEmployee Command
- A EmployeeRegistered Event
Employee Aggregate has firstname, lastname, email, and some VO's like Address, Telephone etc.
It is the root of Worker Entity, so somewhere in my app i have a mapping of Employee Aggregate Id (UUID, domain generated) and Worker Entity Id (integer, database generated)
Command side:
On RegisterEmployee command, do i need to pass all the data needed to hydrate all Employee's fields ?
Then i would have a very big constructor with firstname, lastname, email, address, telephone1, telephone2 etc etc.
Cannot i give only basic fields in the command (firstname, lastname, email) and pass the Worker Entity ID, so that the RegisterEmployee Command handler can retrieve in the database the telephone and adress fields to pass to aggregate ?
Event side:
On the Event side, if my EmployeeRegistered Event Handler has to project a readmodel of my employee, does it need to have all the informations in the event itself to build the readmodel ?
Or can i put in the EmployeeRegistered event's payload only the basic info (firstname, lastname, email) and Worker Entity ID, so that the projection scripts does itself some join in the database to retrieve some complex and hidden informations ?
[EDIT]
Maybe the RegisterEmployee tries to do too many stuffs, and i should:
- dispatch a simple RegisterEmployee command with basics stuffs
- dispatch some other commands like AddEmployeeTelephone, AddEmployeeAdrress, etc
But in that case, doesn't it break a principle that a Registration action should occur in the same transaction ? what if my RegisterEmployee successes and the others don't ? i would end up with an incomplete Employee Registration process ?
[EDIT 2 ]
Hi Bola, you pointed it right. My context occurs in a migration from a legacy application to a cqrs one (at least some parts).
So as i want to let the legacy app do its own stuff, i only listens to persistence events on the db side and from them i dispatch domain commands.
That is why i can imagine having a command holding the "just persisted" entity id, in order to not duplicate the fields of the entity in the command, and to lighten the plumbing.