Categories: Architectural

CQRS (Command Query Responsibility Segregation) Nedir?

Bu makalemde kimine göre basit bir pattern kimine göre de architectural bir yaklaşım olan
CQRS yani Command Query Responsibility Segregation (Komut ve Sorgu Sorumluluklarının Ayrışması) konusunun kısaca üzerinde duruyor olacağız.

Son zamanlarda gözlemlediğim kadarıyla yabancı bloglar da ve stackoverflow üzerindeki tartışmalarda CQRS‘in yavaş yavaş popülerliğini kazanmakta ve hala anlaşılması üzerinde soru işaretleri olan bir pattern türü olduğunu görüyorum.

Bende araştırmalarıma farklı kaynaklardan yola çıkarak (makalemin sonunda paylaşacağım sizlerle) hem benim kavrayabilmem hem de kavraya bildiklerimi sizlerle paylaşabilmem amaçlı bu makaleyi yazmaya karar verdim. 🙂

Haydi bir bakalım neymiş bu CQRS?

CQRS pattern’i Greg Young ve Udi Dahan tarafından tanıtılmış ve onlar da bu fikri Command Query Separation isimli Bertrand Meyer‘in “Object Oriented Software Construction” kitabından esinlenerek almışlardır.

CQS altındaki ana fikir:

Bir method objenin durumunu değiştirmelidir yada geriye bir sonuç dönmelidir fakat her ikisini birden değil.

Biraz karışık gelmiş olabilir. Şimdi birde Wikipedia değimiyle bakmak gerekirse, eğer geriye dönecek değerler referentially transparent (birazdan değineceğim) ise ve hiçbir yan etkiye sahip değilse (referentially transparent fonksiyonun yan etkisi yoktur) method’lar geriye bu değerleri dönmelidir.

Referentially Transparent: 

Herhangi bir fonksiyonun çıktısının sadece girdisine bağlı olması durumudur diyebiliriz ve yukarıda belirttiğim gibi yan etkisi yoktur ve aynı parametreler verildiğinde daima aynı sonucu üretir.

CQS‘e göre metotlar iki parçaya ayrılmalıdır:

  • Commands: Objenin veya sistemin durumunu değiştirir.
  • Queries: Sadece sonucu geriye döner herhangi bir objenin veya sistemin durumunu değiştirmez.

Bakıldığında CQS bize method’ların ne yapıp ne yapmadığını anlamamızı sağlıyor. Bu durumda eğer bir dönüş değeri varsa nesnenin durumunu değiştiremez. Eğer nesnenin durumunu değiştiriyorsa, dönüş değeri void olmalıdır. Böylelikle nesneleri daha kolay ele alabilmemizi ve kodumuzun daha readable, structured ve reusable olmasını sağlıyor.

CQRS ise CQS‘in bir uzantısı olarak kabul edilir. CQRS‘in tanımı CQS ile aynıdır fakat ikisi tamamen ayrı patternlerdir. Aralarındaki temel farklılık ise CQRS içinde nesneler, Commands ve Queries olmak üzere iki farklı nesne olarak application level’ında ele alınırlar.

Basit bir servis tanımlayalım CQRS‘i daha iyi ele alabilmek için:

CustomerService

void MakeCustomerPreferred(CustomerId)
Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

Şimdi CustomerService‘e CQRS uygulandığında bize Commands ve Queries işlemlerini yapacak iki farklı nesne verecektir.

CustomerWriteService

void MakeCustomerPreferred(CustomerId)
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

CustomerReadService

Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()

Görünürde çok basit bir işlem olsa da mevcut olan sistem üzerinde birçok problemin çözülmesini sağlamaktadır. Bu service, Read tarafı ve Write tarafı yani Command ve Query olarak iki farklı servise bölünmüştür.

Bu ayrım Command tarafının ve Query tarafının farklı ihtiyaçlara sahip olduğu düşüncesindedir. Böylece data store ve model’i ayırabilmemize olanak sağlamaktadır.

Ne zaman CQRS kullanılmalı?

  • Geniş ve bir çok katılımcının olduğu verilerde(collaborative data veya collaborative domain), çok kullanıcılı sistemlerde, kompleks ve her zaman değişen iş kurallarının olduğu durumlarda kullanılabilir.
  • CQRS ile read ve write işlemleri üzerinde harika performanslar elde edilebilir, bu işlemler optimize edilerek istenirse farklı veritabanlarına da bölünebilir.
  • CQRS altyapısal işlemlerde bizi karmaşık domain logic işlemlerinden kurtulmamızı sağlar.
  • CQRS geliştirme aşamalarını da farklı takımlara bölebilmemizi sağlar ve böylelikle her takım domain logic üzerinde çalışabilir hale gelir.

Avantajlarına baktığımızda göze hoş geliyor fakat haydi CQRS kullanalım deyipte kullanılacak türden değil. Kullanılacağı zaman zaten proje kendisi söyleyecektir. Yukarıdaki maddelerden yola çıkarak uygulamanın ölçeklenebilirliği(scalability) azaldığında ve domain logic git gide kompleks bir hal almaya başladığında uygulanması gerekli bir hale gelecektir.

CQRS ile birlikte kullanılan event sourcing ve consistency üzerine araştırmalarıma devam edeceğim ve elde ettiğim yeni bilgileri bir sonraki makalemde paylaşıyor olacağım.

Şimdilik sağlıcakla. 🙂

Kaynaklar:

https://cqrs.wordpress.com/documents/cqrs-introduction/
http://www.codeproject.com/Articles/555855/Introduction-to-CQRS
http://martinfowler.com/bliki/CQRS.html
https://en.wikipedia.org/wiki/Command%E2%80%93query_separation

Gökhan Gökalp

View Comments

    • O kadar çok yazmam gereken 2. 3. part'lar var ki hangisine dönüp bakmam gerektiğini şaşırıyorum. Açıkcası CQRS üzerinde son dönemlerde fazlasıyla kaynak/konferans olduğunu için yazmayı pek düşünmemiştim. Siz ne düşünüyorsunuz bu konuda?

  • Hocam selam, öncelikle değerli paylaşımlarınız için teşekkür ediyorum.
    Vakit bulabilirseniz CQRS pattern ile çoklu veritabanı sistemleri üzerine bir yazı paylaşırsanız çok memnun olacağım. Bir süredir üzerinde düşünüyorum best practise nasıl olur karar verememekteyim.

  • Gökhan hocam sizin yazılarınızı okumak insanın ufkunu açıyor, bu CQRS konusu ile alakalı yeni yazılar yazmayı bilgileri güncellemeyi .Net ile CQRS olaylarına değinmeyi düşünmezmisiniz acaba. Çalışmalarınızda başarılar dileklerimiz ile.

    • Merhaba, teşekkür ederim güzel düşünceleriniz için. Tekrardan değerlendireceğim farklı bir şey çıkartabilirmiyim diye.

Recent Posts

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Security Scanning, SBOMs, Signing&Verifying Artifacts) – Part 1

{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…

1 month ago

Delegating Identity & Access Management to Azure AD B2C and Integrating with .NET

{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…

5 months ago

How to Order Events in Microservices by Using Azure Service Bus (FIFO Consumers)

{:tr}Bazen bazı senaryolar vardır karmaşıklığını veya eksi yanlarını bildiğimiz halde implemente etmekten kaçamadığımız veya implemente…

1 year ago

Providing Atomicity for Eventual Consistency with Outbox Pattern in .NET Microservices

{:tr}Bildiğimiz gibi microservice architecture'ına adapte olmanın bir çok artı noktası olduğu gibi, maalesef getirdiği bazı…

1 year ago

Building Microservices by Using Dapr and .NET with Minimum Effort – 02 (Azure Container Apps)

{:tr}Bir önceki makale serisinde Dapr projesinden ve faydalarından bahsedip, local ortamda self-hosted mode olarak .NET…

1 year ago

Some Awesome News of .NET 7

{:tr}Bildiğimiz gibi .NET Conf 2022, 8-10 kasım arasında gerçekleşti. Konferans sırasında ise .NET 7 ve…

1 year ago