Skip to content

This repository is a simple demonstration project that demonstrates how to use CQRS Pattern and MediatR library.

Notifications You must be signed in to change notification settings

vmutlu/CQRSAndMediatRUsage

Repository files navigation

🔥 CQRS Pattern MediatR Kütüphanesi İle Nasıl Uygulanır ? 🔥

📌 CQRS Pattern Nedir ?

CQRS, Command Query Responsibility Segregation‘ın kısaltılmış halidir. 'Command' ve 'Query' sorumluluklarının ayrılması prensibini esas alan bir yaklaşımı savunmaktadır.

Biliyoruz ki, bir uygulama üzerinde kullanıcıdan gelen istekler iki türlüdür. Gelen istek(Request), ya mevcuttaki bir veri üzerinde manipülasyon yapar veya olmayan bir veriyi oluşturur ya da mevcut veri üzerinde herhangi bir işlem yapmaksızın direkt okunmasını sağlar. Yani gelen istek ya bir salt okuma işlemi yapar ya da diğer işlemleri yapar. İşte bu işlemlerden read işlemi yapacak olan isteklere Query, diğerlerine Command denmektedir.

  • Command Olmayan veriyi oluşturan ya da var olan bir veri üzerinde güncelleme veya silme işlemi yapan isteklerdir. Örn: INSERT UPDATE DELETE

  • Query Mevcut verileri sadece listelemek, okumak yahut sunmak için read işlemi yapan isteklerdir. Örn: SELECT

CQRS, uygulamalarımızda bu istekleri karşılayacak olan yapılanmaları birbirinden ayırmamızı önermektedir.


📌 CQRS Pattern Uygulaması

CQRS, verileri eklemek, silmek ve güncellemek için 'Command' sınıflarını, okumak için ise 'Query' sınıflarını kullanmaktadır.


https://sefikcankanber.medium.com/cqrs-command-query-responsibility-segregation-nedir-16b196376389

İlk olarak bir uygulama oluşturuyoruz yada var olan bir uygulamamız oldugunu varsayıyoruz. İçerisinde 'CQRS' isminde bir klasör oluşturup ardından içerisine 'Commands', 'Queries' ve 'Handlers' isimlerinde klasörler oluşturalım. Ardından tüm klasörlerin içerisine yukarıda görseldeki gibi gelecek olan request’leri ve cevap olarak döndürülecek olan response’ları tanımlayacağımız 'Request' ve 'Response' klasörlerini oluşturalım.

Commands

Uygulamada yapılacak olan tüm Command'ları tarif edecek sınıfları barındırmaktadır.

  • Request: Yapılacak Command isteklerini karşılayacak olan sınıfları barındırmaktadır.
  • Response: Yapılan Command isteklerine karşılık verilecek olan response sınıflarını barındırmaktadır.

Queries

Uygulamada yapılacak olan tüm Query'leri tarif edecek sınıfları barındırmaktadır.

  • Request: Yapılacak Query isteklerini karşılayacak olan sınıfları barındırmaktadır.
  • Response: Yapılan Query isteklerine karşılık verilecek olan response sınıflarını barındırmaktadır.

Handlers

Uygulamada yapılacak olan tüm Command ya da Query isteklerini işleyecek ve sonuç olarak respose nesnelerini dönecek olan sınıfları barındırmaktadır.

  • CommandHandlers: Yapılan Command isteklerini işler ve response'larını döner.
  • QueryHandlers: Yapılan Query isteklerini işler ve response'larını döner.

Şimdi Command ve Query sınıflarını oluşturalım.

  • #f03c15 Commands
  • CreateProductCommandRequest ve CreateProductCommandResponse class'larımız "Product" ekleme isteklerinde kullanalım.



  • DeleteProductCommandRequest ve DeleteProductCommandResponse class'larımız "Product" silme isteklerinde kullanalım.



  • #f03c15 Queries
  • GetAllProductQueryRequest ve GetAllProductQueryResponse class'larımız tüm "product" verileri elde edilmek istendiğinde kullanalım.



  • GetByIdProductQueryRequest ve GetByIdProductQueryResponse class'larımız id bazlı product sorgulamalarında kullanalım.



  • #f03c15 Handlers
  • CreateProductCommandHandler: Gelen create product isteğinde aşağıdaki 'CreateProductCommandHandler' sınıfı devreye girecek ve 'CreateProduct' isimli metodu üzerinden aldığı 'CreateProductCommandRequest' nesnesindeki değerleri gerçek 'Product' nesnesine dönüştürerek create işlemini gerçekleştirecek ve ardından geriye 'CreateProductCommandResponse' dönerek kullanıcıyı bilgilendirecektir.


  • DeleteProductCommandHandler: Gelen delete product isteğinde aşağıdaki 'DeleteProductCommandHandler' sınıfı devreye girecek ve 'DeleteProduct' isimli metodu üzerinden aldığı 'DeleteProductCommandRequest' nesnesindeki 'Id' değerine karşılık 'Product' nesnesini elde ederek kaynaktan silecek ve ardından geriye 'DeleteProductCommandResponse' dönerek kullanıcıyı bilgilendirecektir.


  • GetAllProductQueryHandler: Gelen product listesi isteğinde aşağıdaki 'GetAllProductQueryHandler' sınıfı devreye girecek ve 'GetAllProduct' isimli metodu üzerinden tüm 'Product'ları çekecek ve 'List' nesnesine dönüştürüp kullanıcıya döndürecektir. Burada 'GetAllProductQueryRequest' nesnesi request olarak gelecektir fakat herhangi bir şarta vs. bağlı bir operasyon gerçekleştirilmeyeceği için içi boş olarak tasarlandığından dolayı herhangi bir işlevsellik göstermemektedir.


  • GetByIdProductQueryHandler: Id bazlı product isteğinde ise aşağıdaki 'GetByIdProductQueryHandler' sınıfı devreye girecek ve 'GetByIdProduct' isimli metodu üzerinden gelen 'GetByIdProductQueryRequest' nesnesindeki 'Id' değerine karşılık 'Product' nesnesi ayıklanıp, 'GetByIdProductQueryResponse' nesnesine dönüştürülüp geriye gönderilecektir.


İşte CQRS tasarımı bu şekilde ve bundan ibarettir. Artık kullanımına geçelim.


  • Benim uygulamam Asp.NET Core uygulaması üzerinden örneklendirme olduğu için ilgili Handler sınıflarını uygulamama servis olarak ekliyorum.


Daha sonra 'ProductsController' isminde bir controller oluşturup içerisinde aşağıdaki gibi endpointlerimi dolduruyorum.


Uygulamamı ayağa kaldırıp ve test ediyorum.



Gördüğünüz üzere CQRS pattern'i bu şekilde manuel olarak tasarlarsak eğer ister istemez hem çok zahmetli bir inşa sürecinde bulunmamız gerekecek hem de controller sınıfında haddinden fazla inject işlemi yapmamız gerekecektir. Nihayetinde hangi Response sınıfının hangi Request sınıfına ait olduğunu ve hangi Handler tarafından işleneceğini irademizle takip etmek mecburiyetindeyiz.

İşte buradaki çoğul model yönetimini daha dinamik bir şekilde sağlayabilmek için Mediator pattern'inden faydalanabiliriz.

📌 Mediator Pattern Nedir ?

Mediator design patternini birbirleriyle ilişkili eş görevli bir grup nesneyi tek merkezden yönetmek ve aralarında gevşek bağlı(loosely coupled) sistemler kurmak istediğimiz durumlarda kullanırız. Mediator patterninden faydalanmak için MediatR Kütüphanesini kullanabiliriz.

Öncelikle uygulamama MediatR Kütüphanesi eşliğinde Asp.NET Core projesi olmasından dolayı dependency injection paketi olan MediatR.Extensions.Microsoft.DependencyInjection kütüphanelerinide yüklemeyi unutmuyorum.


Daha sonra Asp.NET Core uygulamama aşağıdaki gibi MediatR servisini ekliyorum.


  • IRequest, command veya query requestlerini karşılayacak olan sınıflar tarafından implemente edilecek olan bir arayüzdür.


http://www.kamilgrzybek.com/tag/mediatr/

  • IRequestHandler, command veya query requestlerinin işlenmesini sağlayacak olan Handler sınıflarının arayüzüdür. Generic olarak request ve response sınıflarının bildirilmesini ve ilgili sınıfa içerisindeki 'Handle' isimli methodu implemente etmemizi ister.


http://www.kamilgrzybek.com/tag/mediatr/


  • #f03c15 Commands
  • CreateProductCommandRequest ve CreateProductCommandResponse class'larımız




  • DeleteProductCommandRequest ve DeleteProductCommandResponse class'larımız




  • #f03c15 Queries
  • GetAllProductQueryRequest ve GetAllProductQueryResponse class'larımız

**
**


  • GetByIdProductQueryRequest ve GetByIdProductQueryResponse class'larımız




  • #f03c15 Handlers
  • CreateProductCommandHandler class'ımız



  • DeleteProductCommandHandler class'ımız



  • GetAllProductQueryHandler class'ımız



  • GetByIdProductQueryHandler class'ımız


MediatR kütüphanesinin en can alıcı noktasıda bu command ve query sınıflarını controller üzerinde kullanırken oldukça kolay ve sade bir implementasyon gerektirmesidir. Örneği aşağıdaki görselde 😊



About

This repository is a simple demonstration project that demonstrates how to use CQRS Pattern and MediatR library.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages