What is the difference between commands and events in architectures that emphasize events? The only distinction I can see is that commands are usually sourced/invoked by actors outside the system, whereas events seem to be sourced by handlers and other code in a system. However, in many example applications I have seen, they have different (but functionally similar) interfaces.
问题:
回答1:
Commands can be rejected.
Events have happened.
This is probably the most important reason. In an event-driven architecture, there can be no question that an event raised represents something that has happened.
Now, because Commands are something we want to happen, and Events are something that has happened, we should be using different verbs when we name these things. This drives separate representations.
I can see is that commands are usually sourced/invoked by actors outside the system, whereas events seem to be sourced by handlers and other code in a system
This is another reason they are represented separately. Conceptual clarity.
Commands and Events are both Messages. But they are in fact separate concepts, and concepts should be modeled explicitly.
回答2:
After working through some examples and especially the Greg Young presentation (http://www.youtube.com/watch?v=JHGkaShoyNs) I've come to the conclusion that commands are redundant. They are simply events from your user, they did press that button. You should store these in exactly the same way as other events because it is data and you don't know if you will want to use it in a future view. Your user did add and then later remove that item from the basket or at least attempt to. You may later want to use this information to remind the user of this at later date.
回答3:
Also, in addition to all the answers here exposed, an event handler may be able to trigger a command as well after receiving notification that an event occurred.
Say for example that after you create a Customer, you also want to initialize some accounts values, etc. After your Customer AR add the event to the EventDispatcher and this is received by a CustomerCreatedEventHandler object, this handler can trigger a dispatch of a command which will execute whatever you need, etc.
Also, there are DomainEvents and ApplicationEvents. The difference is simply conceptual. You want to dispatch all your domain events first (some of them may produce Application Events). What do I mean by this?
Initializing an account after a CustomerCreatedEvent has occurred is a DOMAIN event. Sending an email notification to the Customer is an Application Event.
The reason you shouldn't mix them is clear. If your SMTP server is temporarily down, that doesn't mean that your DOMAIN OPERATION should be affected by that. You still want to keep a non-corrupted state of your aggregates.
I usually add events to my Dispatcher at the Aggregate Root level. This events are either DomainEvents or ApplicationEvents. Can be both and can be many of them. Once my command handler is done and I am back in the stack to the code that execute the Command handler, then I check my Dispatcher and dispatch any other DomainEvent. If all of this is successful, then I close the transaction.
If I have any Application Events, this is the time to dispatch them. Sending an email doesn't necessarily need an open connection to a database nor a transaction scope open.
I strayed away a little bit from the original question but it is also important for you to understand how events may also be conceptually treated differently.
Then you have Sagas.... but that's WAYYYY OFF of the scope of this question :)
Does it make sense?
回答4:
They are represented separetly because they represent very different things. As @qstarin said commands are messages that can be rejected, and that on success will produce an event. Commands and events are Dtos, they are messages, and they tend to look very similar when creating and entity, however from then on, not necessarily.
If you are worried about reuse, then you could use commands and events as envelopes to your (messge) payload
class CreateSomethingCommand
{
public int CommandId {get; set;}
public SomethingEnvelope {get; set;}
}
however, what I d like to know is why are you asking :D ie do you have too many commands/events?
回答5:
In addition to the conceptual differences mentioned above, I think there is another difference related to common implementations:
Events are typically processed in a background loop that needs to poll the event queues. Any party interested in acting on the event may, usually, register a callback that is called as a result of the event queue processing. So an event may be one to many.
Commands may not need to be processed in such a manner. The originator of the command will typically have access to the intended executor of the command. This could be, for example, in the form of a message queue to the executor. Thus a command is intended for a single entity.
回答6:
I think something to add to quentin-santin's answer is that they:
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Source.