cqrs - Domain logic in command handler or event handler? -
i using cqrs , ddd build application.
i have account entity, transaction entity , transactionline entity. transaction contains multiple transactionlines. each transactionline has amount , points account.
if user adds transactionline in transaction has transactionline points same account 1 new transactionline, want add new transactionline amount existing one, preventing transaction having 2 transactionlines point same account.
ex :
before command : transaction transactionline1(amount=100, account=2) transactionline2(amount=50, account=1) command : addnewtransaction(amount=25, account=1) desired result : transaction transactionline1(amount=100, account=2) transactionline2(amount=75, account=1) // add amount (50+25) instead of 2 different transactionlines instead of transaction transactionline1(amount=100, account=2) transactionline2(amount=50, account=1) transactionline3(amount=25, account=1) // error, 2 different transactionlines point same account
but wonder if best handle in command or event handler.
if case handled command handler
before command : transaction transactionline1(amount=100, account=2) transactionline2(amount=50, account=1) command : addnewtransaction(amount=25, account=1) // detects case dispatches event transactionlineamountchanged(transactionline=2, amount=75)
addtransactionline command received
check if transactionline exists in new transactionline's transaction same account
if so, emit transactionamountchangedevt event
otherwise, emit transactionaddedevt event
corresponding event handler handles right event
if case handled event handler
before command : transaction transactionline1(amount=100, account=2) transactionline2(amount=50, account=1) command : addnewtransaction(amount=25, account=1) dispatches event transactionlineadded(transactionline=3, amount=25) handler // detects case transactionline2.amount = 75
addtransactionline command received
transactionlineadded event dispatched
transactionlineadded handled
check if added transaction's transactionline points same account existing transactionline in account
if so, add amount of new transactionline existing transactionline
otherwise, add new transactionline
neither commands nor events should contain domain logic, domain should contain domain logic. in domain, aggregate roots represent transaction boundaries (not transaction entities, transactions logic). handling logic within commands or events bypass boundaries , make system brittle.
the right place logic transaction entity.
so best way be
addtransactioncommand finds correct transaction entity , calls transaction.addline(...), logic , publishes events of happened transactionlineaddedevent or transactionlinechangedevent depending on happened.
Comments
Post a Comment