CQRS PATERN

Esra YAŞIN
GoTurkiye

--

Yazılım projelerinde kod tekrarı yerine esnek ve performanslı mimariler uygulamak clean kod yazmamızı sağlar.N-Tier architecture , Onion Architecture bunlardan bazılarıdır. Yazılım mimarileri; değişikliklerden minimum etkilenmemizi sağlar. Projenin yeniden düzenlenmesini, bakımını, genişletilmesini kolaylaştırır.

Öncelikle çok karıştırılan Onion Architecture ve Clean Architecture kavramlarına bakalım.

Onion Architecture; dıştan merkezdeki katmanlara doğru tek yönlü bağlılık oluşturan mimaridir. Her katman sadece bir içteki katmana bağımlılık gösterir.Bir katmanda yapılan değişikliğin içe doğru bir bağlayıcılığı olmadığı için merkeze doğru olan katmanları etkilemeyecektir.

Avantajları; tek yönlü içe doğru bağımlılığı olmasından Loosely Coupled(Gevşek Bağlanma)’yı sağlamaktadır. Birim test uygulanırken her modül için ayrı katmanlar oluşturulacağından daha iyi test edilebilirlik sağlar.

CQRS ise; bu mimariler üzerinde uygulanan bir patterndir.

CQRS; Command Query Responsibility Segregation‘ın kısaltılmasıdır. Command ve Query işlemlerinin ayrılması prensibine dayanır.

COMMAND: Insert,Update,Delete operasyonlarını yapar.Nesnede değişiklik yapar.

QUERY: Select operasyonlarını yapar.Sadece sonuç geriye döner, nesnede değişiklik yapmaz.

  • Command ve Query operasyonlarının ayrılması; performansı, ölçeklenebilirliği, test edilebilirliği artırır
  • Birden çok veritabanları ile çalışmamızı sağlar.Örneğin; Read operasyonları için MySql kullanılırken, Write operasyonları için MongoDb kullanılabilir.
  • Command ve Query işlemlerinin birbirinden bağımsız olması, işlemlerin birbirlerini beklemeden gerçekleşmesini sağlar.Performansı artırır.

Mediator PATERN

MediatR kütüphanesi; Mediator Patterni kullanmamızı sağlar. Aynı interface üzerinden türeyen nesneler arasındaki iletişimi, tek bir nokta üzerinden sağlar. Tıpkı Uçakların hepsinin tek bir kule ile iletişime geçip birbirleriyle doğrudan iletişime geçmemesi gibi.

Bu yüzden; Cqrs tasarımını kolay kullanabilmek için MediatR kullanıyoruz.

MeadiatR;

  • Hangi request’in hangi Handle’i işleyeceğini kendi bulur.
  • Karmaşık ilişkileri yönetmemizi sağlar.
  • Controller’a haddinden fazla Injection yazmaktan kurtarır.

CQRS Pattern Projede Nasıl Kullanılır?

Onion Architecture üzerinde CQRS + MediatR pattern’i uygulanan, AutoMapper ile mapleme işlemleri ve Fluent Validation ile validation kontrollerinin yapıldığı ProgrammigLanguages projesini inceleyelim:

CorePackages ve DevsProject klasörleri içine Katmanlar oluşturulur.

DİKKAT: Projede; New SolutionFolder ile klasörler oluşturuluyor ancak dosya yoluna bu klasörleri oluşturmuyor! Dosya uzantısına gidip manuel olarak klasörü oluşturmamız gerekiyor. Umarım bu Bug biran önce düzeltilir…

Application katmanında Features klasöründe -> Commands ve Queries klasörleriyle işlemler ayrıldı. Features bazında işlemler yapılır yani her entity’e ait klasör oluşturulur. Ve entity ile alakalı tüm işlemler burada yapılır. Languages entitysi için; Command klasöründe herbir işlem için Command sınıfı oluşturulur (CreateLanguageCommand, DeleteLanguageCommand, UpdateLanguageCommand).

CreateLanguageCommand’de Handler sınıfında repository’deki ekleme metotu kullanılarak Language oluşturma işlemi gerçekleştirilir:


// Programlama Dili eklemek için kullanılan komut sınıfı
public class CreateLanguageCommand: IRequest<CreatedLanguageDto>
{
public string Name { get; set; }

// Programlama Dili eklemek için kullanılan işleyici sınıf
public class CreateLanguageCommandHandler : IRequestHandler<CreateLanguageCommand, CreatedLanguageDto>
{
private readonly ILanguageRepository _languageRepository;
private readonly IMapper _mapper;
private readonly LanguageBusinessRules _languageBusinessRules;

public CreateLanguageCommandHandler(ILanguageRepository languageRepository, IMapper mapper, LanguageBusinessRules languageBusinessRules)
{
_languageRepository = languageRepository;
_mapper = mapper;
_languageBusinessRules = languageBusinessRules;
}

public async Task<CreatedLanguageDto> Handle(CreateLanguageCommand request, CancellationToken cancellationToken)
{
await _languageBusinessRules.LanguageNameCanNotBeDuplicatedWhenInserted(request.Name);

Language mappedLanguage = _mapper.Map<Language>(request);
Language createdLanguage = await _languageRepository.AddAsync(mappedLanguage);
CreatedLanguageDto createdLanguageDto = _mapper.Map<CreatedLanguageDto>(createdLanguage);

return createdLanguageDto;
}
}
}
}

Controller’da çağırırken de MediatR ile veriler Commande gönderilir:

 [HttpPost]
public async Task<IActionResult> Add([FromBody] CreateLanguageCommand createLanguageCommand)
{
//CreateLanguageCommand clasında-> Mediator; Handle'nı bulur ve Dto tipinde sonuç döner
CreatedLanguageDto result = await Mediator.Send(createLanguageCommand);
return Created("", result);

Projenin devamına https://github.com/ysnesra/ProgrammingLanguagesProject linkinden ulaşabilirsiniz.

CQRS Pattern ile karmaşık olan Object Mapping işlemleri kolaylaşlaşmaktır. Ve hatalar daha kolay ve hızlı yakalanıp, kolay test edilebilmektedir.

Geri dönüşlerinizi bekliyorum.İyi Çalışmalar…

--

--