SharpNoiZy
SharpNoiZy

Reputation: 1119

Two big question marks about CQRS

I'm a C# developer but I read nearly every tutorial about cqrs out there, doesn't matter if the language was Java, because I want to learn the structure and base of cqrs.

But now I think, the fact that I read so much tutorials is the problem because there are differences in the tutorials and now I'm confused and don't know which technique I have to use.

Two main questions are running wild in my head and maybe some of you can bring some clarity in there.

  1. On the command side, where should I place the logic to call my ORM for example? Some tutorials do that in the command handler (what is more logic to me) and some do it in the event handlers which will be fired by the command handler which in that case do only validation logic.

  2. For the event store and to undo thinks, which data do I have to save into the db, some tutorials save the aggregate and some save the event model.

I hope that someone can explain me what pattern to use and why, maybe both in different scenarios, I don't know.

An practical example would be great. (Only pseudo code)
Maybe a User registration, RegisterTheUser command:

Things to do:

Kind regards

EDIT: Here is my current implementation (Simple)

public class RegisterTheUser : ICommand
{
    public String Login { get; set; }

    public String Password { get; set; }
}


public class RegisterTheUserHandler : IHandleCommand<RegisterTheUser, AccountAggregate>
{
    public void Handle(AccountAggregate agg, RegisterTheUser command)
    {
        if (agg.IsLoginAlreadyInUse(command.Login))
            throw new LoginIsAlreadyInUse();

        agg.AddUserAccount(command);

        CommandBus.Execute<SendMail>(x => { });

                    EventBus.Raise<UserIsRegistred>(x => { x.Id = agg.UserAccount.Id; });
    }
}


public class UserIsRegistred : IEvent
{
    public Guid Id { get; set; }
}


public class AccountAggregate : AggregateBase
{
    public AccountAggregate(IUnitOfWork uow)
    {
        UnitOfWork = uow;
    }


    private IUnitOfWork UnitOfWork { get; set; }


    public UserAccount UserAccount { get; set; }


    public void AddUserAccount(RegisterTheUser command)
    {
        UserAccount = new UserAccount
        {
            Id = Guid.NewGuid(),
            IsAdmin = false,
            Login = command.Login,
            Password = Crypto.Sha512Encrypt(command.Password)
        };

        UnitOfWork.UserAccountRepository.Add(UserAccount);

        UnitOfWork.Commit();
    }


    public Boolean IsLoginAlreadyInUse(String login)
    {
        var result = UnitOfWork.UserAccountRepository.SingleOrDefault(x => x.Login == login);

        return (result != null);
    }
}

Upvotes: 1

Views: 541

Answers (1)

David Hoerster
David Hoerster

Reputation: 28701

So a number of questions, but I'll take a stab at answering.

On the command side, where should I place the logic to call my ORM for example?

Having this logic either in the command handler or in your event handler, to me, really depends on the type of system you're building. If you have a fairly simple system, you can probably have your persistence logic in your event handlers, which receive events raised by your domain. The thinking here is that your commands handled by the command handler will already have the information needed and your command handler ends up being not much more than a router. If you need more complexity in your command handler, such as dealing with sagas, long running transactions, or some additional layer of validation, then your command handler will use your persistence layer here to pull out data (and perhaps write data) and then route the command to the proper domain or issue more commands or raise events. So I believe it really depends on the level of complexity you're dealing with.

I tend to favor simplicity over complexity when starting out, and would probably look at having that logic in the event handler to begin with. Move to the command handler if your system is more complex.

For the event store and to undo thinks, which data do I have to save into the db, some tutorials save the aggregate and some save the event model

I'm not exactly sure what you're asking here, but if you're asking what should be stored in your event store, then I think a simple solution is the aggregate id, the aggregate type, the event with data (serialized) and the event type. Off the top of my head, that's probably the bare bones of what you'd need: based on the aggregate id you're working with, get all the events for that aggregate (in order raised) and then replay them to rebuild the aggregate. I don't think you need to save the aggregate unless there's some compelling reason to (which is always possible).

As for your request for a practical example and the steps you laid out, that's probably a question in and of itself, but my thoughts on that are:

  • Check if the user name is already in use Depending on your application, you may want to do this from the read side in your controller (or whichever layer is raising commands) before you issue a command. Validate at that point, but you'd probably want to validate again before persisting it. You could do that in your event handler where it would probably catch an exception because you're violating a unique index in your database.

  • Add user to DB Again, my thought is keep it simple and handle it in your event handler, since your domain is raising a UserIsRegistered event.

  • Send confirmation email Your domain could raise the UserIsRegistered event and a second event handler (EmailHandler) would also subscribe to that event and send out the email.

  • ConfirmationMailSent event could be raised by the event handler, added to the event queue and handled accordingly. I guess I'm not sure what you want to happen here.

But, hopefully this helps a bit.

Upvotes: 1

Related Questions