Skip to content

Transitioning to Event Sourcing, part 3: commands

by Julien on July 22nd, 2010

Une version française de ce billet est disponible ici.

Overview

This refactoring is more subtle than the previous one. In part 1, I already stated it was crucial to have one method in an aggregate root for each use case your domain is supporting. We will now take it to the next level by making those use cases explicit, in the form of commands. The architecture becomes:

Note that the UI is now completely isolated from the domain (or the other way around?)

Benefits

Isolation

The UI has no more dependencies to the domain model anymore. The 2 will be allowed to evolve separately.

Communication

Creating classes for commands is just recognizing that commands are an important component of the domain model and the ubiquitous language. They are capturing use cases (or stories). For example, a user could ask:

  • I want to create students.
  • I want to create classes.
  • I want to register students to classes.

The commands will crystallize these user’s expectations.

Opportunities

Capturing commands explicitly opens some interesting opportunities. For once, you could log all the commands easily. Doing so, you would capture everything users wanted to perform on the system.
Decoupling command execution from the UI also brings interesting choices. In the sample, commands are executed right away, in the same thread as the controller. But it would be easy to send the command to one or multiple application servers instead (using NServiceBus for example). This could allow your application to easily scale when it needs it, with a very little cost.

Implementation

What changed

2 new projects have appeared in the solution:

The first one is hosting the commands. The other one contains the command handlers. The command handlers are responsible for coordinating domain entities to answer to a command.

Commands are dispatched from the UI to the domain by a bus.

Issuing a command

The result is even simpler controller code. For example:

public RedirectToRouteResult DoCorrectName(StudentDTO model)
{
    var cmd = new CorrectStudentNameCommand(model.Id, model.FirstName, model.LastName);
    commandBus.Send(cmd);

    return RedirectToRoute(new
    {
        controller = "Student",
        action = "Index"
    });
}

The bus will channel the command to the appropriate IHandleCommand<T> handling method:

public void Handle(CorrectStudentNameCommand cmd)
{
    var student = studentRepository.ById(cmd.StudentId);

    if (student != null)
    {
        student.CorrectName(cmd.FirstName, cmd.LastName);
    }
}

Guidelines

The guidelines explained in Part1 do also apply here:

  • One command will be executed on only one aggregate root.
  • Only one method of the aggregate root should be called in the command handler.

Running the sample

The sources for the entire serie is available on GitHub at http://github.com/jletroui/TransitioningToEventSourcing
.

To run it, simply create a new “DDDPart3″ database in SQLExpress.

Transitioning to Event Sourcing posts:

From → Event Sourcing

12 Comments
  1. Perhaps a better way to conceptualise the domain when you’re talking about communication benefits is this:

    I want to enroll students.
    I want to create classes.
    I want to register students to classes.

    Instead of ‘creating’ students, ‘enrolling’ them seems to make more domain sense.

    I’m still struggling to move away from a CRUD mentality.

  2. Julien permalink

    scceroos, you are right. We should never “create” a person in software. Mothers do that alone. Even for the classes, “I want to declare classes” might be more appropriate. Actually, most of the time, the business has already better terms for such operations. Listening to your business expert is a great part of DDD.

  3. malicksarr@gmail.com permalink

    Bonjour,

    Juste pour un encouragement. Sympa de vulgariser le DDD. Grâce à votre article, j’ai progressé dans ma compréhension de la mise en oeuvre des principes du DDD.

    Merci encore !

  4. Hey just wanted to give you a quick heads up and
    let you know a few of the pictures aren’t loading correctly.
    I’m not sure why but I think its a linking issue.
    I’ve tried it in two different internet browsers and both show the
    same outcome.

Trackbacks & Pingbacks

  1. Transitioning to Event Sourcing, part 1: the DDD “light” application | Julien's blog
  2. Transitioning to Event Sourcing, part 2: go CQRS with DTOs | Julien's blog
  3. Transitioning your DDD “light” application to CQRS and Event Sourcing | Julien's blog
  4. Transitioning to Event Sourcing, part 4: track state changes | Julien's blog
  5. Julien Letrouit on Transitioning Brownfield Apps « CQRS
  6. Transitioning to Event Sourcing, part 5: use events for updating your domain database | Julien's blog
  7. Transitioning to Event Sourcing, part 6: store events | Julien's blog
  8. Transitioning to Event Sourcing, part 7: build a view model | Julien's blog

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS