Event Sourcing and CQRS are friends

What will we cover

  • Who the hell is this guy.
    • A quick introduction.
  • What are bottom up estimates.
  • Quick demo of what I am building.
  • Third Party Service and Libraries.
  • Programming patterns I am using.

Aaron

Gravypower

  • https://blog.gravypower.net
  • @gravypower
  • https://github.com/gravypower

 

Command Query Responsibility Segregation (CQRS)

Steven van Deursen

AKA .NET Junkie

Command Query Responsibility Segregation (CQRS)

Where?

Asking a question should not change the answer.

Bertrand Meyer

Meyer, Bertrand. "Eiffel: a language for software engineering" (PDF). p. 22. Retrieved 16 December 2014.

Bertrand Meyer first introduced the idea as a part of of his work on the Eiffel programming language.

https://en.wikipedia.org/wiki/Command–query_separation

Command Query Responsibility Segregation (CQRS)

What?

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

var command = new ChangeChannel
{
    ChannelId = channelId
};
public class ChangeChannelCommandHandler
{
    private readonly TV _tv;

    public ChangeChannelCommandHandler(TV tv)
    {
        _tv = tv;
    }
 
    public void Handle(ChangeChannelCommand command)
    {
        // Change the Channel
    }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class TvController
{
    private readonly ChangeChannelCommandHandler handler;
 
    public TvController(ChangeChannelCommandHandler handler)
    {
        this.handler = handler;
    }
 
    public void ChangeChannel(int channelId)
    {
        var command = new ChangeChannelCommand
        {
            ChannelId = channelId,
        };
 
        this.handler.Handle(command);
    }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

var query = new GetChannelQuery();
public class GetChannelQueryHandler
{
    private readonly TV _tv;

    public GetChannelQueryHandler(TV tv)
    {
        _tv = tv;
    }
 
    public int Handle(GetChannelQuery query)
    {
        return _tv.Channel;
    }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class TvController
{
    private readonly ChangeChannelCommandHandler _changeChannelCommandHandler;
    private readonly GetChannelQueryHandler _getChannelQueryHandler;
    
    public TvController(
    	MoveCustomerCommandHandler changeChannelCommandHandler,
    	GetChannelQueryHandler getChannelQueryHandler)
    {
        _changeChannelCommandHandler = changeChannelCommandHandler;
        _getChannelQueryHandler = getChannelQueryHandler;
    }
 
    public void ChangeChannel(int channelId)
    {
       ...
    }
    
    public int GetChannel()
    {
        var query = new GetChannelQuery();
 
        return _getChannelQueryHandler.Handle(query);
    }
}

Command Query Responsibility Segregation (CQRS)

So what Aaron, why should I care about this pattern?

Single Responsibility

SOLID principles 

  • Single Responsibility
  • Open Closed
  • Liskov Substitution
  • Interface Segregation
  • Dependency Inversion

Command Query Responsibility Segregation (CQRS)

So what Aaron, why should I care about this pattern?

Boundaries that you can decorate

Command Query Responsibility Segregation (CQRS)

So what Aaron, why should I care about this pattern?

Boundaries in an application give you and opportunity to add cross cutting concerns or targeted aspects to your logic

We can do this in CQRS by created interfaces for the command and query handlers, and use the decorator structural pattern.

public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

Command Query Responsibility Segregation (CQRS)

So what Aaron, why should I care about this pattern?

public class ChangeChannelCommandHandler : ICommandHandler<ChangeChannelCommand>
{
    private readonly TV _tv;

    public ChangeChannelCommandHandler(TV tv)
    {
        _tv = tv;
    }
 
    public void Handle(ChangeChannelCommand command)
    {
        // Change the Channel
    }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class TvController
{
  private readonly ICommandHandler<ChangeChannelCommand> _handler;

  public TvController(ICommandHandler<ChangeChannelCommand> handler)
  {
    _handler = handler;
  }

  public void ChangeChannel(int channelId)
  {
    var command = new ChangeChannelCommand
    {
      ChannelId = channelId,
    };

    _handler.Handle(command);
  }

  public void GetChannel()
  {
    ...
  }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class LivingRoom
{
  private const int ABCKidsChannel = 24;
  private readonly TvController _tvController;
  
  public LivingRoom(TvController tvController)
  {
    _tvController = tvController;
  }
 
  public void EnterRoom()
  {
    if(_tvController.GetChannel() != ABCKidsChannel)
    {
      //Chnage the channel to ABC Kids
      _tvController.ChangeChannel(ABCKidsChannel);
    }
  }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class House
{
  public LivingRoom LivingRoom;

  public void LivingRoom()
  {
    var tv = new TV();
    var changeChannelCommandHandler = new ChangeChannelCommandHandler(tv);
    var tvController = new TvController(changeChannelCommandHandler);
    LivingRoom = new LivingRoom(tvController);
    LivingRoom.EnterRoom();
  }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class GuardFromChannelNineDecorator : ICommandHandler<ChangeChannelCommand>
{
  private const int NineEntertainment Channel = 9;
  private readonly ICommandHandler<TCommand> _decoratee
  private readonly TV _tv;

  public ChangeChannelCommandHandler(TV tv, ICommandHandler<ChangeChannelCommand> decoratee)
  {
    _tv = tv;
    _decoratee = decoratee;
  }
 
  public void Handle(ChangeChannelCommand command)
  {
    if(command.ChannelId == NineEntertainment)
    {
      throw new System.InvalidOperationException("You can not watch Married at First Sight");
    }

    decoratee.Handle(command);
  }
}
public class GuardFromChannelNineDecorator : ICommandHandler<ChangeChannelCommand>
{
  private const int NineEntertainment Channel = 9;
  private const int ABCKidsChannel = 24;
  
  private readonly ICommandHandler<TCommand> _decoratee
  private readonly TV _tv;

  public ChangeChannelCommandHandler(TV tv, ICommandHandler<ChangeChannelCommand> decoratee)
  {
    _tv = tv;
    _decoratee = decoratee;
  }
 
  public void Handle(ChangeChannelCommand command)
  {
    if(command.ChannelId == NineEntertainment)
    {
      command.ChannelId = ABCKidsChannel;
    }
      
    decoratee.Handle(command);
  }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class House
{
  public LivingRoom LivingRoom;

  public void LivingRoom()
  {
    var tv = new TV();
    var changeChannelCommandHandler = new ChangeChannelCommandHandler(tv);
    
    var guardFromChannelNineDecorator = 
      new GuardFromChannelNineDecorator(tv, changeChannelCommandHandler);
    
    var tvController = new TvController(guardFromChannelNineDecorator);
    LivingRoom = new LivingRoom(tvController);
    LivingRoom.EnterRoom();
  }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

public class House
{
  public LivingRoom LivingRoom;

  public void LivingRoom()
  {
    var tv = new TV();
    var changeChannelCommandHandler = new ChangeChannelCommandHandler(tv);
    
    var turnTvOffAfterFiveAttemptsDecorator = 
    	new TurnTvOffAfterFiveAttemptsDecorator(tv, changeChannelCommandHandler);
    
    var guardFromChannelNineDecorator = 
      new GuardFromChannelNineDecorator(tv, turnTvOffAfterFiveAttemptsDecorator);
      
    
    var tvController = new TvController(guardFromChannelNineDecorator);
    LivingRoom = new LivingRoom(tvController);
    LivingRoom.EnterRoom();
  }
}

Command Query Responsibility Segregation (CQRS)

Just show me the code Aaron.

var container = new Container();

container.Register(
  typeof(ICommandHandler<ChangeChannelCommand>),
  typeof(ChangeChannelCommandHandler));

container.RegisterDecorator(
  typeof(ICommandHandler<ChangeChannelCommand>),
  typeof(TurnTvOffAfterFiveAttemptsDecorator));

container.RegisterDecorator(
  typeof(ICommandHandler<ChangeChannelCommand>),
  typeof(GuardFromChannelNineDecorator));

Note not all DI libraries are created equally, some may not support syntax like this.

Command Query Responsibility Segregation (CQRS)

Cross-Cutting Concerns

In aspect-oriented software development, cross-cutting concerns are aspects of a program that affect other concerns.

https://en.wikipedia.org/wiki/Cross-cutting_concern

Link to my Blog

Event Sourcing and CQRS are friends

By Aaron Job

Event Sourcing and CQRS are friends

  • 310