18

The difference between a command and an event in bus communication seems a little vague to me. I know that commands should be executed once only, while an event can be handled multiple times, but still I'm not sure when to use a command or an event.

Let's look at an example:

When a new user registers to a web application, we should create him an account and send a confirmation email.

Creating the account - this seems to be the right spot to send a CreateUserCommand to the bus and let a specialized component handle it.

Or maybe this shouldn't even be implemented with an asynchronous bus communication? We want the user to ba able to log in into the application right away. With the bus we have no guarantee when the command will be executed.

Sending email - after the component creates the account I can see 2 possibilities

  1. Send another command to the bus SendConfirmationEmailCommand
  2. Publish an event UserAccountCreatedEvent

And than let the email sender component grab it and to it's job.

On one hand I want the confirmation email to be sent once only (use a command), on the other hand, I believe there can be multiple components interested in newly registered users. A logger or maybe an SMS sender.

How would you implement it?

Andrzej Gis
  • 973
  • 9
  • 17

1 Answers1

19

In principle, a command describes a request that is to be executed, whereas an event describes something that has happened:

  • A command requires some action to be performed by a processor, and this action should be performed only once by this processor.

  • An event is the notification of some action that was already executed or an external happening. Several processors/agents may be interested in knowing about the event. Several of them may further issue commands or action required by this notification in their domain of responsibility.

In your scenario, I understand that:

  • CreateUserCommand is a command
  • UserAccountCreatedEvent is an event that should be issued when CreateUserCommand is successfully completed by the account management service

Now there are two possibilities:

  1. The account management service issues itself a SendConfirmationEmailCommand on the bus, because it expects this command to be executed by a more specialized service.
  2. The account management service does nothing more than sending the event notification on completion, and leaves to another service (e.g. communication service, subscription service, etc...) the decision on whether or not to email/sms/etc... and if necessary to issue a SendConfirmationEmailCommand command to be performed by some gateway.

If you have opted for a service bus approach, it would make sense to use the flexibility that this allows, i.e. to favor option 2.

Christophe
  • 74,672
  • 10
  • 115
  • 187
  • Thanks, that clears things out. Two more questions about option 2: 1. How will the account management service know about completion of the command? I believe it's by listening to the events published by specialized services upon completion of their tasks - than what is the real purpose of the account management service? To republish the events? It seems redundant. 2. I also didn't understand who is supposed to issue the SendConfirmationEmailCommand. Account management service or the "another service"? – Andrzej Gis Oct 02 '16 at 19:28
  • 1) my assumption was that account management service performed itself the job and send the event when its finished successfully (i.e. encountered no errors). But you are right: it's possible that account management service sends itself commands to a persistence/database service and has to monitor job completion event (e.g. an asyncrhonous answer). – Christophe Oct 02 '16 at 20:31
  • @gisek 2) in a service bus, I'd imagine that you have very specialized services, each having a limited responsibility. In this case Account Management only performs the creation and notifies whoever is interested that it's done. Some other service would then monitor things to react. For instance, you could have a communication manager, who'd be in charge to apply business rules to decide when and how to communicate events to users. If you'd do 1)+2) in the same service, you'd hardly need a service bus. – Christophe Oct 02 '16 at 20:35
  • Just curious: isn't sending a command to the bus some kind of leaking abstraction or tight coupling? I thought the whole point of using pub/sub architecture is that one service doesn't need to know or dictate what other services need to do. Instead, you just let others know what had happened, which is represented by events. – David Liang Oct 04 '22 at 20:24
  • @DavidLiang Not really. I'm sure it's possible to leak some abstractions internals using commands, but the other way round is far from being systematic. If the command is "scale shape by x%", you would just need to know that the shape can be scaled (which is an abstraction, and the definition of a scaling is independent of any concrete shape, whereas the implementation needs some polymorphic interaction between the command and the shape). – Christophe Oct 04 '22 at 20:52
  • @Christophe: thanks for replying so quickly. Ok probably it's not a leak of abstractions, but what about tight coupling or dictating other services what to do? Isn't the service sending out the command dictating the whole world what to do? – David Liang Oct 04 '22 at 20:55
  • 1
    @DavidLiang I see what you mean. But in a command based approach, your abstractions are commands/requests, which are specific to a domain, and subjects on which the command apply. So indeed, having commands related to manipulating shapes, will not be usable if the subjects are not shapes. You may then consider that the commands require the whole world to be shapes. You may instead prefer to reframe the problem, reconsidering what the subjects should be and what the commands could do with the subjects. It's really case by case that you need to proceed to spot real coupling issues – Christophe Oct 04 '22 at 21:02