CQRS Nedir? Mediator Pattern .NET Örnek Proje
Okuma ve yazma işlemlerinin birbirinden ayrışarak kaynakların daha performanslı kullanılmasını amaçlayan bir Design Pattern. Okuma işlemleri QUERY olarak adlandırılır ve data döner; yazma işlemleri de COMMAND olarak adlandırılır ve sadece veri tabanını günceller geriye data dönmez.
Veri tabanlarının birbirinden ayrıştırılmış olmasını savunan bu yapıda aynı tip veri tabanı kullanmak zorunlu değildir. Projenin yapısı gereği Command istekleri için ilişkisel veri tabanlarından MySQL, PostgreSQL, MSSQL kullanılırken Query istekleri için okuma hızı çok daha yüksek Elasticsearch, Apache Cassandra, MongoDB gibi NoSQL veri tabanları tercih edilebilir.
CQRS Pattern’in uygulandığı senaryolarda veri tabanları birbirinden ayrıştığı için Command için kullanılan veri tabanında bu veri tabanlarının da birbirleriyle eşitlenmesi gerekmektedir.
Bu problem aşağıdaki yöntemler ile çözüme kavuşturulabilir:
- Message Queueing: Komut isteğinde yapılan değişiklikler kuyruk yapısı aracılığıyla asenkron bir şekilde okuma için kullanılan veri tabanına aktarılabilir.
- Change Data Capture (CDC): Yazma veri tabanında yapılan değişiklikler loglanabilir ve bu loglar izlenerek değişiklik yapıldığında okuma veri tabanında gerekli işlem gerçekleştirilebilir.
- API Request: Yapılan değişikler bir API aracılığıyla diğer veri tabanında da tetiklenebilir/aktarılabilir.
- Event Sourcing: Yapılan değişikler event olarak kaydedilerek daha sonra senkronizasyon için kullanılabilir.
CQRS hangi durumlarda tercih edilmelidir?
- Okuma işlemlerinin yazma işlemlerine nazaran daha fazla olduğu senaryolar (Örneğin E-Ticaret siteleri)
- Projeyi geliştiren ekibin okuma ve yazma için farklı takımlara ayrıldığı senaryolarda bakımı kolaylaştırmak istendiğinde
- Farklı sistemler ile olan entegrasyonlarda yaşanabilecek aksaklıkları minimuma indirmek istendiğinde
CQRS’in sağladığı avantajlar nelerdir?
- Okuma ve yazma işlemleri birbirinden ayrıldığı için bağımsız bir şekilde ölçeklendirilebilir
- İlişkisel veriler okuma tarafında iç içe tutularak karmaşık JOIN sorgularından uzak durmamızı sağlar
- Sürdürülebilir ve esnek kod yapısı sağlar. Çoğunlukla karmaşık akışlar yazma kısmında bulunduğu için okuma kısmı daha basit bir yapıya sahip olur
CQRS’in getirdiği dezavantajlar nelerdir?
- Büyük projelerde bu yapıyı uygulamak sistem tasarımında karmaşıklığa sebep verebilir
- Veri tabanı senkronizasyonu doğru bir şekilde sağlanamadığı takdirde tutarsız verilerin işlenmesi/gösterilmesi gibi problemler ortaya çıkabilir
Mediator Pattern Nedir?
CQRS Pattern’in uygulanmasıyla beraber ortaya çıkan karmaşık yapıyı merkezi bir noktadan yönetebilmek için geliştirilmiş bir yazılım tasarımıdır.
Controller seviyesinde her bir Handler’ın yer alması, okunurluğu ve kod yönetimini zorlaştırmaktadır. Mediator Pattern kullanılmadan önce örnek bir Controller sınıfı aşağıdaki gibi görünmekte:
Mediator Pattern kullanıldıktan sonra ise aşağıdaki gibi bir kod yapısı ortaya çıkmaktadır:
.NET’de Mediator Pattern’i uygulamak için sıklıkla tercih edilen MediatR paketi kullanılabilir.
MediatR Nasıl Çalışıyor?
CQRS Pattern’i uygularken oluşturulan Request-Response modelleri bir interface üzerinden birbirleriyle ilişkilendirilerek gelen Request’e göre doğru Handler’e yönlendirilmesini ve oradan da doğru Response’un gelmesini sağlayarak isteklerin tek bir noktadan yönetilmesini sağlar.
MediatR, Handler sınıflarının bir zincir şeklinde tetiklenmesini de sağlayabiliyor. Buna ise Chain of Responsibility Pattern adı verilmektedir.
CQRS Örnek Proje
Temelleri daha iyi anlamak için oluşturmuş olduğum projeyi çalıştırarak CQRS yapısını deneyimleyebilirsiniz. Projedeki tek eksik veri tabanları arasında senkronizasyon yapılmamasıdır. Bunu ise farklı bir yazıda anlatmayı ve aynı projeye dahil etmeyi planlıyorum.
Projeyi docker ile ayağa kaldırılabilecek şekilde ayarladım fakat veri tabanlarını Docker’da, servisi Visual Studio üzerinden ayağa kaldırmak isterseniz DbContext sınıflarındaki bağlantı adreslerini localhost olarak düzeltmeniz gerekecektir.
Proje Linki -> https://github.com/enescaakir/CQRS-WebAPI
NOT: Projeyi ayağa kaldırırken dikkat edilmesi gereken adımları README dosyasında bulabilirsiniz.
Kaynaklar:
- Yusuf Yılmaz — CQRS Design Pattern Nedir, Neden Kullanılır? Bir CQRS Design Pattern İncelemesi
- DotnetCurry — Command Query Separation (CQS) A simple but powerful pattern
- Gencay Yıldız — CQRS Pattern Nedir, Mediatr Kütüphanesi ile Nasıl Uygulanır
- Yunus Emre Haslak — CQRS Pattern ile Repository Pattern Kullanımı
- Refactoring Guru — Mediator