repositorydrycqrsduplication

CQRS code duplication in commands


I have a question about code duplication in the command side of the CQRS principle.

Been following the articles from:

https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91 https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92

It seems to me that this approach of separating each command in it's own class is going to give some code duplication when retrieving the entities from the data store.

A bit contrived perhaps but let's say for example I have a command where I want to reset a users password given his email-address and a command where I want to update the user's last login date.

public class ResetPasswordCommandHandler : CommandHandler<ResetPasswordCommand>
{
    public override void Execute(ResetPasswordCommand command)
    {
       **// duplication here**
        var user = from c in db.Users
            where c.EmailAddress = command.EmailAddress
            select c;

        user.EmailAddress = command.EmailAddress;
        ...
        db.Save();
   }
}

public class UpdateLastLoginCommandHandler : CommandHandler<UpdateLastLoginCommand>
{
    public override void Execute(UpdateLastLoginCommand command)
    {
       **// duplication here**
        var user = from c in db.Users
            where c.EmailAddress = command.EmailAddress
            select c;

        user.LastLogin = DateTime.Now;
        ...
        db.Save();
   }
}

In both commands I retrieve the user based on his email-address. Now if I would like to trim the UI input before querying the database I would have to change this in two places.

I Could of course create a UserRepository which would e.g., have a method GetUserByEmailAddress and insert that IUserRepository into the constructor of my CommandHandlers. However, wouldn't this eventually create a "god repository" with Save, GetById, GetByUsername, etc?

And if I create a repository why create the separate Query objects?

How would one go about keeping this code DRY?


Solution

  • Why not refactor your Command Handler into one that implements multiple interfaces:

    public class UserCommandHandler : CommandHandlerBase, 
                                      IHandle<ResetPasswordCommand>,
                                      IHandle<UpdateLastLoginCommand>
    {
        public void Execute(ResetPasswordCommand command)
        {
            var user = GetUserByEmail(command.EmailAddress);
    
            user.EmailAddress = command.EmailAddress;
            ...
            db.Save();
       }
    
        public void Execute(UpdateLastLoginCommand command)
        {
            var user = GetUserByEmail(command.EmailAddress);
    
            user.LastLogin = DateTime.Now;
            ...
            db.Save();
       }
    
       private User GetUserByEmail(string email) {
                return (from c in db.Users
                       where c.EmailAddress = command.EmailAddress
                       select c).FirstOrDefault();
       }
    }
    

    This way, you can refactor private helper methods within the command handler, you command handler can handle similar commands, and you reduce your code duplication. You also won't need the "god" repository.

    Personally, I'd rather have the private GetUserByEmail helper as a separate query class that I inject the db context in through the constructor, so that GetUserByEmail is a very specific class that gets me a User.

    Hope this helps.