First, here is some the distinction between a Command and an Event.
A command express what you want to do. Usually expressed with a verb in the present tense:
A event express what actually happened. Usually expressed with a verb in the past tense;
As you can anticipate, what you request is not always what actually happens:
A Command is still an Event ?
Let’s go a bit meta.
The fact that you decide you want to do something is something that happens in time. So it can also be considered as an event !
True… but what’s the usefulness of this ?
Someone who would like to study the correlation between your desires and their realizations will model both as events..
This can be the same in a tracking context. Track both causes and effects..
Should we just ignore the distinction then ?
Surely not !
It’s here again a matter of context. Of Bounded Context.
Let’s take a sample with different kind of concepts, Value Object and Entities, to highlight how the same thing can take different modeling forms in different contexts:
Money is usually modeled as a Value Object, which implies equality by Value. I give you $10 you give me $10, we’re even, even if I give you a bill and you give me some coins.
In the context of fraud tracking, this can be very different. Bills have a tracking number, and you can model it as entity.
If you make both context work together you’ll go through an Anti Corruption Layer for context mapping. You’ll not model all your accounting with entities for money because some other context models it this way !
In the case of Command and Events, some contexts can be interested in the fact that a decision was made, so this will be modeled as an event. But in the context where this decision happens, the decision is different from the actual outcome, and not being clear about this difference can lead to several issues..
For example if you model a withdrawal with a Withdrawal concept: It is not clear whether it represe,ts the fact that you asked it to happen or the fact that is has actually been done.
Being explicit on it with WithdrawMoney / MoneyWithdrawn removes the ambiguity.
In the context of event sourcing, this distinction is very important as the previous article showed. As is the distinction between upstream events and internal events, since upstream events is input and will only produce things you’d like to happen, so are closer to commands from the system point of view.
Of course if your context is not about time and decision, don’t use these concepts that would be useless. You’re writing a compiler ? Forget about all this.
Should I have Command DTOs ?
not necessarily, a command can be modeled as a function/method call. So creating Command object is not mandatory.
It can still be useful for dispatch, storage for diagnostics, functional test etc.