CQRS (Command Query Responsibility Segregation) Nedir?
Merhaba,
Bu yazıda CQRS Pattern hakkında konuşuyor olacağız. İlk olarak,
CQRS ( Command Query Responsibility Segregation ) nedir ile başlayalım.
CQRS :
Komutlar (Command) ve sorgular (Query) arasındaki sorumlulukları
ayırma prensibine dayanan bir yazılım mimari desenidir. 2000'li yılların başında Greg Young tarafından önerilmiş olan bu desen,
yazılım uygulamarında okuma (Query) ve yazma (Command) işlemlerini
birbirinden ayırmayı hedefler.
Komutlar (Command), sistemin durumunu değiştiren yani sistem içerisindeki veriler üzerinde değişiklikleri ifade ederken;
sorgular (Queries), sistemin durumunu değiştirmeden veriler üzerinde değişiklik yapmayan veri okuma işlemlerini temsil eder. Bu ayrım sayesinde, her iki tür işlem için en uygun depolama ve işleme teknikleri kullanılabilir, sistem daha kolay ölçeklenir, bakımı ve okunması daha kolay gelir.
CQRS, özellikle büyük, karmaşık ve yüksek performans gereksinimleri olan sistemlerde tercih edilen bir yaklaşımdır. Ancak, bu yaklaşımın uygulanması sistem karmaşıklığını arttırabileceği için, ihtiyaç ve bağlam dikkate alınmalıdır. CQRS daha güçlü ve esnek bir mimari oluşturabilir, ancak aynı zamanda sistem tasarımı ve uygulanması üzerindeki yükü de arttırabilir.
Ya Command Query diyip duruyoruz nedir abicim bu Command Query?
Gelin birlikte bakalım...
Görselde de gördüğümüz gibi;
Command : INSERT , UPDATE , DELETE komutlarını barındırır. Veri üzerinde değişiklik yapmamızı sağlar.
Query : SELECT komutu, Veri üzerinde değişiklik yapmayıp sadece okuyan, listeleyen, raporlayan sorgulardır.
CQRS Pattern’ni Neden Kullanmalıyız?
İşin en başından başlamak gerekirse;
Dediğimiz gibi kullanıcıdan gelen istekler iki türlüdür.
İsteklerden birisi veri üzerinde değişiklik yapan, olmayan veriyi oluşturan vb. (Command), bir diğer istek türümüz ise veri üzerinde değişiklik yapmayan, okuyan, listeleyen (Query)'dir. CQRS , uygulamalarımızda bu iki isteği birbirinden ayırmamızı önermektedir.
Tamam da ayırmalıyız diyip duruyoruz neden ayırıyoruz?
Şimdiye kadar genellikle basit ölçekli bir projede sorgulama ve güncelleştirme için aynı veri tabanını ya da veri modelini kullanıyorduk. Temel CRUD(Create-Read-Update-Delete) yaklaşımı ile sistem performansını ve maaliyetini çok düşürmeden kullanım için yeterli bir yol idi. Ancak sistemler geliştikçe, daha komplike hale dönüştüğü zamanlarda karşımıza 'domain logic işlemleri' çıkabilir. Object mapping karmaşık bir hale gelebilir. Veri yazma işleminde ise validation ve business logic gibi multi işlem gerçekleştiren bir durumla karşı karşıya kalabiliriz. İşte bu yüzden, Greg Abimiz "Commmand ve Query" yapısının ayrı olması gerektiğini önerir.
Bu klasik yaklaşımda diyelim ki binlerce ürüne sahip bir sistemde binlerce kullanıcı bu ürünleri listelemek istiyor. API kısmında sürekli her kullanıcı için bir 'Select' sorgusu çalışacak aynı zamanda bu veriler üzerinde değişikliğe gidilmek istenirse sistem üzerinde çok büyük bir performans kaybına neden olmakta.
CQRS
CQRS modelde ise; Command ve Query için ayrı bir Request ve Response nesnesi bulunmakta ayrıca yazımızda daha önceden bahsetmediğimiz Handler kavramını da bu görselde görmekteyiz.
Handler Nedir?
Handler adını verdiğimiz sınıflar yapılacak olan tüm Command veya Query isteklerini işleyip, sonuçları döndürdüğümüz sınıflardır.
Ayrıca görselde gördüğümüz gibi Query için ayrı bir veri tabanı, Command için ayrı bir veri tabanı kullanılmakta. Pratik yaklaşımda tek bir veri tabanı veya birden fazla veri tabanı kullanılabilir. Bu kullanımların her ikisi için de avantaj ve dezavantajlar bulunmakta.
Tek Veri Tabanı:
Avantaj: Consistincy için ekstra bir efor harcanmaz ve yapıyı kompleks hale getirmez.
Dezavantaj: Indexlerden kaynaklı Write işlemlerini yavaşlatacağından ve Read işlemleri için kompleks sorgular kullanmak zorunda kalacağımızdan dolayı performans kaybına sebep olur.
Çoklu Veri Tabanı:
Avantaj: Read/Write işlemlerinin gereksinimlerine yönelik veri tabanı seçimi ( RDBMS vb.) yapabilmek. Uygun Data Structure kullanabilmek.
Dezavantaj: Kompleks bir yapı olması ve Eventual Consistency olması.
CQRS'nin Faydaları:
- Görev Ayrımı
- Performans
- Bağımsız Ölçeklenme
- Basitlik
CQRS Pattern Tasarım ve Uygulaması:
İlk olarak kullanacağımız uygulamada veya katman içerisine CQRS isimli bir klasör oluşturarak başlayabiliriz(Futures klasörü). Devamında Commands ve Queries için ayrı iki klasör daha oluşturuyoruz. Dilerseniz Handler için de ayrı bir klasör oluşturabilirsiniz.
Bu projede her bir işlem kendi klasörü içerisinde Response, Request ve Handler sınıflarını barındırıyor.
Command ve Queries kavramlarını konuşmuştuk peki bu kavramlar içerisinde bulunan 'Request ve Response' sınıfları nedir?
Request: Yapılacak olan istekleri karşılayacak sınıflardır.
Response: Yapılan isteklere karşılık verilecek sınıflardır.
Handler: Uygulamada yapılacak olan tüm Command veya Query isteklerini işleyecek ve sonuç olarak respose nesnelerini dönecek olan sınıftır.
LoginUserResponseModel, RequestMode ve Handler
Bu yazıda CQRS Pattern'i inceledik. Burada çoğu model yönetimini daha dinamik bir şekilde sağlayabilmek ve kodumuzu daha pratik geliştirebilir bir hale getirebilmek için Mediator Pattern'dan yararlanabiliriz. Bir sonraki yazıma bakarak Mediator Pattern Nedir? ve CQRS ile kullanımını görebilirsiniz.
Sonraki yazılarımda görüşmek üzere
İyi çalışmalar.
Comments (5)
Haticesays:
Temmuz 13, 2024 at 4:11 pmBilgilendirici bir yazı olmuş, Emeğine sağlık.
guvenrdvansays:
Temmuz 14, 2024 at 6:04 pmTeşekkürler.
Sümeyyesays:
Temmuz 14, 2024 at 9:37 pmMakalenizden destek alarak kendi kodumda kullandım teşekkür ederim
guvenrdvansays:
Temmuz 14, 2024 at 11:21 pmBen teşekkür ederim yazımı okuduğunuz için.
MediatR Nedir? CQRS ile Kullanımı – Rıdvan Güvensays:
Temmuz 24, 2024 at 10:18 pm[…] Nedir?MediatR bir CQRS kütüphanesidir. Bir aracı olarak da bahsedilebilir.Bir önceki CQRS yazısında bahsettiğim gibi CQRS deseninin uygulamasını kolaylaştırmak için kullanılır. Asıl amacı […]