Usando o Padrão CQS (Command Query Separation) no ASP.NET

Em projetos ASP.NET, é comum enfrentarmos desafios para manter a clareza e a organização do código. O padrão Command Query Separation (CQS) surge como uma solução para esse problema, separando operações de leitura e escrita. Neste post, vamos explorar o conceito do CQS e como implementá-lo com o ASP.NET e a biblioteca MediatR.

O que é o Padrão CQS?

O padrão Command Query Separation (CQS) foi proposto por Bertrand Meyer e promove a divisão clara entre métodos que modificam o estado do sistema (commands) e métodos que retornam dados (queries). Em resumo:

  • Commands: Executam ações que modificam o estado do sistema (ex.: criar um pedido).
  • Queries: Realizam operações de leitura que retornam dados sem alterar o estado (ex.: buscar um pedido).

Essa separação aumenta a legibilidade, facilita os testes e reduz o acoplamento. Também antecede outro padrão muito popular, o CQRS (Command Query Responsibility Segregation), falaremos mais sobre ele em outro post. 

CQS flow


Vantagens de Usar CQS no ASP.NET

1. Código Mais Legível

Cada método tem uma responsabilidade única, o que torna o código mais fácil de entender.

2. Facilidade de Teste

Commands e queries podem ser testados de forma isolada, facilitando a criação de testes unitários.

3. Manutenção Simplificada

A separação entre leitura e escrita torna a manutenção do código menos arriscada e mais segura.

Estrutura de Commands e Queries

No ASP.NET, uma forma comum de estruturar o CQS é criar pastas específicas para commands e queries dentro da camada de aplicação. Além disso, o uso de um Mediador, como o MediatR, ajuda a desacoplar as operações e a manter o código organizado.

Implementação de CQS com MediatR no ASP.NET

1. Instalando o MediatR

Para usar o MediatR, adicione-o ao seu projeto via NuGet Package Manager:


    	dotnet add package MediatR
        dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
    

2. Criando um Command e seu Handler

Aqui está um exemplo de um Command para criar um pedido e seu handler:


public class CreateOrderCommand : IRequest<OrderResponse>
{
    public int ProductId { get; set; }

    public int Quantity { get; set; }

    // Outras propriedades relevantes
}

public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, OrderResponse>
{
    public async Task<OrderResponse> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        // Implementa a lógica de criação do pedido

        // Retorna uma resposta (se aplicável)
    }

}

3. Criando uma Query e seu Handler

Para operações de leitura, usamos uma query e seu handler correspondente:


public class GetOrderByIdQuery : IRequest<OrderDetailsDto>
{
    public int OrderId { get; set; }
}

public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, OrderDetailsDto>
{
    public async Task<OrderDetailsDto> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
    {
        // Lógica para buscar o pedido pelo ID
    }
}

4. Registrando o MediatR no ASP.NET

No arquivo Startup.cs, registre o MediatR para que ele resolva automaticamente os handlers:


    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMediatR(typeof(CreateOrderCommandHandler).Assembly);
        // Outros serviços
    }

5. Utilizando Commands e Queries no Controller

No Controller, você pode utilizar o IMediator para despachar commands e queries:


    [ApiController]
    [Route("api/orders")]
    public class OrdersController : ControllerBase
    {
        private readonly IMediator _mediator;

        public OrdersController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpPost]
        public async Task<IActionResult> CreateOrder([FromBody] CreateOrderCommand command)
        {
            var result = await _mediator.Send(command);
            return Ok(result);
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetOrder(int id)
        {
            var query = new GetOrderByIdQuery { OrderId = id };
            var result = await _mediator.Send(query);

            return Ok(result);
        }
    }

Conclusão

O padrão CQS é uma ótima maneira de estruturar aplicações ASP.NET, especialmente em cenários complexos. A separação entre commands e queries organiza a lógica de negócio, tornando o código mais modular e fácil de manter. Experimente essa abordagem para melhorar a estrutura e escalabilidade do seu sistema!

Tags: ASP.NET, CQS, MediatR, Commands, Queries, Boas Práticas de Programação

Comentários

Postagens mais visitadas deste blog

Diário de bordo: como a autoavaliação pode transformar sua carreira

Resiliência em Aplicações Asp.Net