Why are commands and events separately represented?
Asked Answered
M

11

106

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.

Maddie answered 10/2, 2011 at 21:13 Comment(3)
It depends heavily what you exactly have in mind when you use the words "command" and "event".Vaud
Take your typical CQRS/DDD project as an example.Maddie
My understanding: Commands must be processed by exactly one receiver (which can reject the command), and Events can be processed by 0...n receivers.Mackmackay
P
196

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.

Parolee answered 11/2, 2011 at 0:7 Comment(8)
Okay, are there practical, implementation-level differences between them? For example, a different interface?Maddie
Yes, I would say primarily in dispatching. Commands are dispatched to a single handler, but events are dispatched to multiple listeners. Granted, the implementation differences are in the buses, but I still use separate event and command interfaces, so that each bus only takes the messages it can.Parolee
With commands you use the word "Send" (you care about the target of this operation), whereas with events you use "Publish" (you don't care who's on the other end).Blamable
@Parolee I know this is old, but I wish I could upvote your answer like 10 times... I was about to go down the route of "why isn't everything an event, some of them just get acted on" -- e.g. "SomethingRequested" and then "SomethingHappened"Honea
Consider an entity being persisted in mysql and raising event entityIndexed. The same event is listened by an index-service which on receving the event fetch the entity and index it in elasticsearch. Would you still call it an event or a command from index-service perspective?Amplifier
@Amplifier You have both an event and a command there. It sounds like you've mixed the concerns of handling the event and performing the index command in the same implementation, but logically you have both.Parolee
@quentin-starin, I think what I described is a very common pattern called event notification, where an independent service would receive / consume an event and take appropriate action. I too agree with you that its a mix between event and command based on the perspective we see it from. My question is, is there a solution pattern to it or is it fine and is not a bad thingAmplifier
I like your answer and it makes sense to me, but would you mind adding some relevant sources or references?Stalinabad
P
20

The event is a fact from the past.

The command is only a request, and thus may be refused.

Commands Events
Purpose Invoke Behavior Something Happened
Ownership Command Owned by Consumer Event Owned by Publisher
Consumers One Consumer Zero or Many Consumers
Senders Many Senders Single Publisher
Naming Verb Past Tense

An important characteristic of a command is that it should be processed just once by a single receiver. This is because a command is a single action or transaction you want to perform in the application. For example, the same order creation command should not be processed more than once. This is an important difference between commands and events. Events may be processed multiple times because many systems or microservices might be interested in the event. 'msdn'

Puckett answered 24/3, 2019 at 14:28 Comment(0)
N
9

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?

Northwesterly answered 28/12, 2016 at 18:57 Comment(2)
But you could just as easily argue you have Domain Events, Application Events and User Events. Then it just becomes about what the source of the event is. I do understand how the distinction can be useful, but perhaps more in making a distinction between a request and a response/action resulting from it. But even there I am not yet totally convinced yet. Need to do more investigating.Repetitive
So, now that I read my own response I can see the confusion. The events may actually be one. Events. Then you have the handlers who may have that distinction. You may have two handlers for the same event, then you can trigger them in different contexts. You can decide to trigger "Domain Event Handlers" within the active Transaction and then after, you can trigger your "Application Event Handlers". I just don't see the point of sending an email or sms within a Transaction. Maybe you can add a "task" to a database and have another process executing them, like sending emails. Does it make sense?Northwesterly
F
8

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.

Fu answered 1/12, 2014 at 10:4 Comment(5)
In the way described by @quentin-starin, thinking of the event as something that has happened and a command as something we want to happen (a request), doesn't stop button press events being recorded, it's just that those events don't necessarily result in a command, or result in a command that has been acted upon.Augustineaugustinian
I'm still of the opinion that commands are redundant. I just call what I do functional event sourcing. A recent blog of mine with ES and F# Elm as a complete system: anthonylloyd.github.io/blog/2016/11/27/event-sourcingFu
Commands decouple local events from remote actions. In your example the consumer of the UserPressedButton event won't react to a UserSelectedMenu or ScriptDidSomething unless it knows about these things too. In addition, commands are generally directed at a particular consumer; again, in your example, the consumer of the UserPressedButton event can't tell if the user had the "Confirm" check box checked or not, unless we add even more coupling. With commands, the action taken can depend on the state of the sender or even an external policy. Events, alone, make this nearly impossible.Kerby
Check out this project - github.com/gregoryyoung/m-r . It uses both commands and events.Abeabeam
It's easier to distinguish commands from events when thinking of the strictest implementation: event sourcing. Here the events are the single source of truth. You can build your full state at any time by only replaying the events. The commands in contrast are requests which might result in events, but also might get rejected. For rebuilding the state commands are unimportant. So if your system fails to process a command (e.g. due to validation errors) it is okay. If your system fails to process an event, your state will be corrupted.Acetyl
N
5

Just to add to these great answers. I'd like to point out differences with regards to coupling.

Commands are directed towards a specific processor. Thus there is some level of dependence/coupling with the Command initiator and the processor.

For example, a UserService upon creating a new user sends a "Send Email" Command to the EmailService.

The fact that the UserService knows that it needs the EmailService, that is already coupling. If EmailService changes its API schema or goes down, it directly affects the UserService function.


Events are not directed towards any specific event handler. Thus the event publisher becomes loosely coupled. It does not care what service consumes its event. It's even valid to have 0 consumer of an Event.

For example, a UserService upon creating a new user publishes a "User Created Event". Potentially an EmailService can consume that event and sends an email to the user.

Here the UserService is not aware of the EmailService. They are totally decoupled. If the EmailService goes down, or changes business rules, we only need to edit the EmailService


Both approaches have merits. A purely Event Driven Architectural design is harder to track since it is too loosely coupled, especially on large systems. And a Command heavy Architecture have high level of coupling. So a good balance is ideal.

Hope that makes sense.

Nutt answered 13/8, 2020 at 21:22 Comment(0)
H
2

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?

Hughmanick answered 11/2, 2011 at 14:32 Comment(5)
No, I don't have too many as I am looking to build my first such system! :) I am in learning mode. I am trying to understand if CommandHandlers and EventHandlers do anything different, or basically have the same interface.Maddie
An interesting point to learn is that commands and events can be different, for example say you have a CheckoutCartCommand, the event will probably have a lot more data than the command, there might be many commands too. Would highly reocomend you have a look at github.com/MarkNijhof/Fohjin and github.com/gregoryyoung/m-rHughmanick
With regard to your example, envelopes are usually on the outside, not on the inside (e.g. a soap envelope). And I think there's a property name missing (Payload?).Blamable
@Yves: well given that the Something evelope has information essential to the command (if this was customer creation think email) I would find that rather strange, dont you think?Hughmanick
I don't think you grasp the concept of an envelope. If you have things specific to the command then put them in the command, either as payload or as headers (out-of-band). But don't call the payload/headers an envelope.Blamable
H
2

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.

Headcheese answered 5/7, 2016 at 11:39 Comment(0)
O
2

You cannot recompute a state based on commands, because in general they can produce different outcomes each time they are processed.

For example, imagine a GenerateRandomNumber command. Each time it's invoked it will produce a different random number X. Thus, if your state depends on this number, each time you recompute your state from the commands history, you'll get a different state.

Events solve this problem. When you execute a command, it produces a sequence of events that represent the outcome of the command execution. For example, the GenerateRandomNumber command could produce a GeneratedNumber(X) event that logs the generated random number. Now, if you recompute your state from the events log, you'll always get the same state, because you'll always use the same number that was generated by a particular execution of the command.

In other words, commands are functions with side-effects, events record the outcome of a particular execution of a command.

Note: You can still record a history of commands for audit or debugging purposes. The point is that to recompute the state, you use the history of events, not the history of commands.

Orizaba answered 21/3, 2020 at 11:29 Comment(1)
An excellent observation. Pardon me that my own answer touches on the same while adding still more nuance.Prendergast
C
1

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.

Comprehensible answered 28/12, 2016 at 2:54 Comment(0)
P
1

Let's throw the functional core, imperative shell pattern into the mix. Events correlate to the functional core and commands to the imperative shell. That is, events reside in the pure and commands in the impure. The shell, like any CLI, handles the impurities.

This can be seen in that commands are validated and sometimes rejected. It can also be seen in that commands can rely on operations not permitted in the world of events. For example, rolling dice in a game of Backgammon involves issuing a roll command and its result when generated would be memorialized in a rolled event. The value of this separation can be further seen in the ability to source or replay events.

While live events may bubble up to the shell and cause new commands to be issued, replayed events cannot. They must cause no further side effects.

Prendergast answered 25/1, 2023 at 16:46 Comment(0)
S
0

Expanding on the concepts from @LeviFuller comment, I also used command and event patterns to represent "exactly one" and "0 or more" listeners respectively, but in a different way from @froi answer, where both are still decoupled.

In this architecture, a command publisher still does not know who is going to process the command (much like with events). The difference is that the publisher is assured that someone will process the command. So while you could model any command as an event, it would be undesirable to do so, because the publisher doesn't have that assurance.

This becomes especially important when considering the transition between command processors. A transition may occur in many scenarios - for example, if the command processor is a network service, it may need to go down for maintenance; alternatively, in a UI based application, the command processor could represent the screen the user is on, and the user is moving to a different screen.

During a transition, you typically want to ensure that commands coming in are only processed by the new processor. The old processor would deregister itself as soon as possible, meaning that there may be a gap while no processor is registered for the command type - and the command hub (analogous to an event hub) should maintain a queue of commands received during this time. This may also include partially processed commands from that time, as the old processor should resubmit the "work still to do" after deregistering itself.

None of this would be possible using events. If nobody is listening to an event, it means nobody cares about it, and that's okay. Events would not need to be queued in that case. If an event subscriber had not finished processing an event at the time it begins to shut down, there's typically no need to resubmit the "work still to do" as it's no longer relevant. Events are "fire and forget" in that there is no expectation of what happens after they are submitted, but with a (valid) command there is an expectation that something will be done, even during a transition.

Soggy answered 14/6, 2023 at 21:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.