CQRS (Command Query Responsibility Segregation) yazma (Command) və oxuma (Query) əməliyyatlarının idarəedilmə məsuliyyətlərini bir-birindən ayıran memarlıq patternidir.
Unutmayın: CQRS ≠ DDD. DDD biznes domenini modelləşdirir; CQRS isə yalnız əməliyyatların ayrılmasına fokuslanır.
CQRS-in əsas prinsipləri
- Ayrılma (Separation): Əmr (Command) sistemin vəziyyətini dəyişir (yaratmaq, yeniləmək, silmək) və kənar təsirləri ola bilər. Sorğu (Query) isə yalnız oxuma (read-only) əməliyyatıdır, vəziyyəti dəyişmir.
- Əmrlər (Commands): Müəyyən hərəkəti yerinə yetirmək üçün lazım olan məlumatları daşıyır. Geriyə birbaşa məlumat qaytarmır; yalnız uğur statusu və ya xəta strukturunu təsdiqləyir.
- Əmr Handler-i (Command Handler): Müvafiq əmri icra edən biznes loqikasını saxlayır. Hər bir əmrin adətən yalnız bir handler-i olur və o, repozitoriyalar və ya Unit of Work ilə işləyir.
- Sorğu (Query): Sistemdən məlumat çəkmək üçün istifadə olunur. Əmrlərdən ayrılmış öz modelinə malikdir və state-i dəyişmir.
- Sorğu Handler-i (Query Handler): Məlumat mənbəyindən verilənləri çəkib uyğun formatda geri qaytarmaq üçün biznes loqikasını birləşdirir.
- Modellər (Models): Ənənəvi memarlıqda eyni model həm oxuma, həm yazma üçün istifadə olunur. CQRS-də performans və aydınlıq üçün əmr və sorğu modelləri ayrılır - bir-birini təkrarlamır.
Nə vaxt CQRS istifadə etməli?
CQRS hər layihə üçün lazım deyil. Aşağıdakı hallarda daha məntiqlidir:
- Oxuma və yazma yükü güclü şəkildə fərqlənirsə (məsələn, dashboard çox oxunur, amma az yazılır).
- Mürəkkəb biznes qaydaları var və handler-lər aydın ayrılmalıdır.
- Read model optimallaşdırılmalıdır (projection, caching, ayrı DB).
- Komanda böyüyür və use case-lər ayrı-ayrı idarə olunmalıdır.
Sadə CRUD tətbiqlərində CQRS əlavə mürəkkəblik yarada bilər - ehtiyac olmadan tətbiq etməyin.
MediatR nədir?
CQRS-in əsas çətinliyi oxuma və yazma əməliyyatlarını ayırarkən memarlığın mürəkkəbliyini artırmasıdır. MediatR bu problemin bir qismini həll etməyə kömək edir: sorğu göndərən tərəf (Controller) ilə sorğunu qəbul edən tərəf (Handler) arasında vasitəçi (mediator) rolunu oynayır.
Handler-i birbaşa Controller-dən çağırmaq əvəzinə sorğunu MediatR-a göndəririk; o, sorğunu doğru handler-ə yönləndirir. Bu, məsuliyyətlərin təmiz ayrılmasına və test edilə bilənliyə kömək edir.
Decoupling
Controller yalnız IMediator ilə işləyir, konkret handler-ləri tanımır.
Pipeline davranışları
Validation, logging, performance ölçümü kimi cross-cutting concern-lər pipeline behavior ilə mərkəzləşdirilir.
Standart axın
Request → MediatR → Handler → Response - bütün use case-lər eyni struktura uyğun gəlir.
Tipik istifadə axını
Controller _mediator.Send(command) çağırır, MediatR uyğun
IRequestHandler<TCommand, TResult> tapır və handler nəticəni qaytarır.