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
Teşekkürler. Güzel yazı hocam.
Bu güzel makale için teşekkür ederim çok yararlı oldu.
Ben teşekkür ederim. Beğendiğinize sevindim.
Teşekkürler faydalı bir yazı
Peki bir sonraki makale için yeterince bilgi birikimi edinebildiniz mi ? 🙂
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?
Gökhan Hocam, sizler yazın severek okuyoruz.. Ekip arkadaşlarıma, çevremde ki kişilere sizin yazılarınızı tavsiye ediyorum
Teşekkür ederim, faydalı oluyorsa ne mutlu bana.
Çok anlaşılır ve güzel bir yazı olmuş elinize sağlık
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.