Reputation: 367
Let's say i have an application structured around the basics of CQRS event sourcing:
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:
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:
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.
Upvotes: 3
Views: 1950
Reputation: 3270
Something's off in the domain model/design. Let me take a step back and outline the ideal way so that you can map the missing pieces.
RegisterEmployee Command
contains all data input for Employee Aggregate
Employee Application Service
receives the command from FrontendEmployee Application Service
initializes Employee Aggregate
, preferably with the help of a factory methodEmployee Aggregate
raises EmployeeRegistered Event
on successful validation and construction of a new Employee objectEmployee Application Service
persists the new Employee object with the help of Employee Repository
EmployeeRegistered Event
is dispatched to the message broker after successful persistence transactionEmployeeRegistered Event
contains the entire dataset required by a subscriberSubscribers
for this Event may be in the same Bounded Context (BC) or in a different BCInterested Subscribers
catch the event and call the relevant Application Service
in their own BCApplication services
initialize infrastructure services and perform transactions (in your case, these are projections)There should be no domain logic in Event handlers.
Upvotes: 2