CQRS pattern - interfaces

前端 未结 2 510
悲哀的现实
悲哀的现实 2021-01-06 15:36

I\'m new at the CQRS pattern, but I\'d like to understand why you should use two interfaces:

public interface IQuery{}
public interface ICommand{}

2条回答
  •  庸人自扰
    2021-01-06 15:40

    If I get it correctly you are confusing acronyms here. From your question to me it seems that you are not really asking about Command and Query Responsibility Segregation pattern, but you might ask about the Command-Query Separation principle.

    And in this case the basics in short are that:

    Commands

    Change the state of a system but do not return a value

    Queries

    Return a result and do not change the observable state of the system (are free of side effects).

    I will try to demonstrate the difference between having a generic interface (and its implementation) and a non-generic interface. A similar way of thinking shown in this demonstration applies to a generic Query Handler.

    Addressing the technological side of your question

    A generic command handler interface as:

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

    Its sample implementation:

    public class ExampleCommandHandler : ICommandHandler 
    {
        public void Handle(ExampleCommand command)
        {
            // Do whatever logic needed inside this command handler
        }
    }
    

    Example Command that you pass into the command handler:

    public class ExampleCommand
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    And finally an example consumer of the Command handler:

    public class ExampleService
    {
        private readonly ICommandHandler commandHandler;
    
        public ExampleService(ICommandHandler handler)
        {
            commandHandler = handler;
        }
    
        public void DoStuff(int id, string name)
        {
            var command = new ExampleCommand
            {
                Id = id,
                Name = name
            };
    
            commandHandler.Handle(command);
        }
    }
    

    Benefits of using a generic ICommandHandler

    Using the generic command handler lets users depend on this abstraction rather than exactly implemented command handlers.

    If you would depend the exact implementation of this ExampleCommandHandler that won't implement the generic interface, the example service's constructor would have a dependency like:

    public ExampleService(ExampleCommandHandler handler)
    

    In this instance, you couldn't decorate this handler because it doesn't implement an interface.

    Also worth noting that with this setup you only need to unit test the Command handler and not the service's DoStuff() method, since the behaviour is in the Command handler.

    Note about CQRS

    CQRS in this picture is a technical difference than an OOP method like CQS.

提交回复
热议问题