Skip to content
This repository has been archived by the owner on Feb 20, 2021. It is now read-only.

Glos command handler

Christopher Bennage edited this page Jan 30, 2015 · 1 revision
  • A Command handler is responsible for dispatching the command to the correct domain object Aggregate root.
  • A command handler checks that the command is correctly formatted ('sanity check'). This check is separate from the Anti-corruption Layer, and verifies that the state of the system is compatible with command execution.
  • A command handler locates the aggregate instance that will action (provide an execution context for) the command. This may require instantiating a new instance or rehydrating an existing instance.
  • A command handler invokes a business method of the aggregate passing any parameters from the command.
  • The aggregate executes the business logic and creates any events inside the business method.
  • After the business method completes, the command handler persists the aggregate's changes to the repository.
  • In Event sourcing, the command handler appends any new events to the event store.
  • The events are published to a topic when the aggregate state is persisted (saving the state and publishing an event may be wrapped inside a transaction).

Comments

IMO it is the aggregate that raises the event; the handler persists or publishes it. Tom Janssens

@ Tom - I think that it could make for a cleaner overall design to divide the responsibility between aggregate and command. Commands participating in ES have one and only one event they can logically raise, and this can be enforced via generic interface implementation, e.g. MyCommand : IDomainEvent - Josh Elster

@ Josh - That is new to me; I never considered a command could only raise one event TBH. - Tom Janssens

Here's a bit of sample code from a command handler in the RI (note that this part of the system is not currently using event sourcing) - Dominic:

public void Handle(MarkOrderAsBooked command)
{
    var repository = this.repositoryFactory();

    using (repository as IDisposable)
    {
        // Locate/rehydrate the aggregate instance
        var order = repository.Find<Order>(command.OrderId);

        if (order != null)
        {
            // Invoke the business method
            order.MarkAsBooked();

            // Persist the changes
            repository.Save(order);
        }
    }
}

Although this part of the system isn't using event sourcing, aggregates do still raise events. So in this example the Order aggregate creates the events, but they're published to the topic inside the repository Save method.