CQRS aşırı mühendisliği değil mi?


16

Hala eski güzel depoları hatırlıyorum. Ancak depolar zamanla çirkinleşiyordu. Sonra CQRS yaygınlaştı. Onlar güzel, temiz bir nefes vardı. Ama son zamanlarda kendime tekrar tekrar neden mantığı bir Kontrolcinin Eylem yönteminde (özellikle eylemin kendi içinde bir tür komut / sorgu işleyicisi olduğu Web Api'de) tutmuyorum soruyorum.

Daha önce bunun için net bir cevabım vardı: Denetleyiciyi tüm bu taşınmaz tek tonlarla ve genel çirkin ASP.NET altyapısıyla test etmek zor olduğu için test için yapıyorum. Ancak zaman değişti ve ASP.NET altyapı sınıfları günümüzde çok daha kolay birim testleri yapıyor (özellikle ASP.NET Core'da).

İşte tipik bir WebApi çağrısı: komutu eklenir ve SignalR istemcileri bu konuda bilgilendirilir:

public void AddClient(string clientName)
{
    using (var dataContext = new DataContext())
    {
        var client = new Client() { Name = clientName };

        dataContext.Clients.Add(client);

        dataContext.SaveChanges();

        GlobalHost.ConnectionManager.GetHubContext<ClientsHub>().ClientWasAdded(client);
    }
}

Kolayca test edebilir / alay edebilirim. Dahası, OWIN sayesinde yerel WebApi ve SignalR sunucularını kurabilir ve bir entegrasyon testi yapabilirim (ve bu arada oldukça hızlı).

Son zamanlarda hantal Komutlar / Sorgular işleyicileri oluşturmak için gittikçe daha az motivasyon hissettim ve Web Api eylemlerinde kod tutma eğilimindeyim. Sadece mantık tekrarlanırsa veya gerçekten karmaşıksa bir istisna yaparım ve onu izole etmek istiyorum. Ama burada doğru olanı yapıp yapmadığımdan emin değilim.

Tipik bir modern ASP.NET uygulamasında mantığı yönetmek için en makul yaklaşım nedir? Kodunuzu Komutlar ve Sorgular işleyicilerine taşımak ne zaman mantıklıdır? Daha iyi kalıplar var mı?

Güncelleme. DDD-lite yaklaşımı hakkında bu makaleyi buldum . Kodun karmaşık kısımlarını komut / sorgu işleyicilerine taşıma yaklaşımım CQRS-lite olarak adlandırılabilir.


1
CQRS'in işleri nasıl daha test edilebilir hale getirdiğini / singletons / kontrolörler / vb. Büyük ölçüde ilgisizler. Ayrıca, (counter?) Örneğinizde hala bir komut oluşturuyorsunuz.
guillaume31

Kodunuzu altyapı koduyla tutarsanız (örn. İstemci ip adresi alın), test edilmesi zordur. Eğer mantığı bir sorgu / komuta ayırırsanız, çok daha kolaydır. Kod örneği biraz kafa karıştırıcı, bu yüzden güncelledim.
SiberianGuy

1
Sorguların ve komutların mantığı yoktur. Onlar aptal DTO'lar. Daha sonra komut / sorgu işleyicileriniz var , ancak bunlar uygulama hizmetleri, etkileşimler, iş hizmetleri ile tam olarak aynı, CQRS olmayan bir bağlamda ... Uygulayıcı / kullanım durum mantığını Denetleyiciden ayrı bir nesneye yerleştirmek CQRS'ye özgü bir şey değildir.
guillaume31

Ayrıca, Singleton'a karşı enjekte edilen bağımlılık sorunu CQRS'ye tamamen diktir. Bir Depo tektonunu çağıran bir CommandHandler singletonunu çağıran bir Denetleyiciniz olabilir ...
guillaume31

1
@ guillaume31, CQRS depo / uygulama hizmeti çağrılarından daha hantal olma eğilimindedir. Genellikle 2-3 sınıfa (yani sorgu, sorgu işleyici, sorgu sonuç), altyapı vb. İhtiyaç duyarlar.
SiberianGuy

Yanıtlar:


17

CQRS nispeten karmaşık ve maliyetli bir model midir? Evet.

Aşırı mühendislik mi? Kesinlikle hayır.

In Martin Fowler CQRS bahsediyor orijinal makaleye bunu uygulanabilir değil CQRS kullanmayan hakkında uyarılar bir sürü görebilirsiniz:

Herhangi bir model gibi, CQRS bazı yerlerde yararlıdır, ancak bazılarında yararlı değildir.

CQRS, ilgili herkes için önemli bir zihinsel sıçramadır, bu nedenle fayda atlamaya değmezse ele alınmamalıdır .

CQRS'in başarılı kullanımlarıyla karşılaşmış olmama rağmen, karşılaştığım vakaların çoğu o kadar iyi değildi ...

Bu faydalara rağmen, CQRS kullanma konusunda çok dikkatli olmalısınız .

... böyle bir sisteme CQRS eklemek önemli bir karmaşıklık getirebilir .

Yukarıdaki vurgularım.

Uygulamanız her şey için CQRS kullanıyorsa, aşırı tasarlanmış CQRS değil, sizin uygulamanızdır. Bu, özellikle yazma eşzamanlılığının büyük bir endişe kaynağı olabileceği yüksek performans / yüksek hacimli uygulamalar gibi bazı belirli sorunları çözmek için mükemmel bir modeldir.

Ve tüm uygulama değil, sadece küçük bir kısmı olabilir.

İşimden canlı bir örnek olarak, sipariş giriş sisteminde CQRS kullanıyoruz ve siparişleri kaybedemeyiz ve binlerce siparişin belirli saatlerde farklı kaynaklardan aynı anda geldiği ani artışlarımız var. CQRS, sistemi canlı ve duyarlı tutmamıza yardımcı olurken, arka uç sistemlerini gerektiğinde bu siparişleri daha hızlı (daha fazla arka uç sunucusu) işlemek ve ihtiyaç duymadığında daha yavaş / daha ucuz işlemek için ölçeklendirmemize yardımcı oldu.

CQRS, aynı veri kümesinde işbirliği yapan veya aynı kaynağa yazan birkaç aktörünüzün olduğu sorun için mükemmeldir.

Bunun dışında, tüm problemlerinize tek bir problemi çözmek için yapılmış bir model yaymak size daha fazla problem yaratacaktır.


Diğer bazı yararlı bağlantılar:

http://udidahan.com/2011/04/22/when-to-avoid-cqrs/

http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/


3
"Nispeten karmaşık ve maliyetli desen" kısmı hariç her şeyi kabul edin. CQRS sadece okumaları yazmalardan ayırıyor. Koli bandı, sıfır ara katman yazılımı / karmaşık takımlar ve daha önce olduğu gibi aynı veritabanını tutarak tüm umurunda yapabilirsiniz.
guillaume31

@ guillaume31, bu adil bir nokta. Ben orijinal soru fikri oldukça temel olduğunu düşünüyorum: "Web Api eylem kendi içinde bir tür komut / sorgu olduğu". Ancak komutlar ve sorgular için ayrı sınıflar kullanmayan herhangi bir CQRS örneği gördünüz mü (tercihen github)? Başkalarının .NET'te CQRS'yi nasıl uyguladığını görmeye çalıştığımda bulduğum şey bu.
SiberianGuy

Evet, ama aşırı mühendislik değil. Bu, kalıbın temel önermesidir - sorguları yazarlardan ayırmak, modeli etki alanı modelinden okumak.
guillaume31

CQRS yaklaşımı birçok bağlamda aşırı öldürme olabilir , ama bu tamamen farklı bir hikaye. Q'nuzda CQRS'ye yanlış atfettiğiniz tüm küçük teknik detaylar nedeniyle aşırıya kaçmıyor, aşırıya kaçıyor çünkü CQRS'nin size getirdiği şeylere her zaman ihtiyacınız yok.
guillaume31

Bence Fowler'in puanı sadece belirli bir nokta için geçerlidir. SQL Views bir tür CQRS'dir ve çağlar boyunca bizimle birlikte ve hiç kimse çok karmaşık olduklarını söylemiyor. CQRS'nin birçok çeşidi, yani olay kaynağı projeksiyonları olduğu için, bazı bölgelerde karmaşık olarak görülebilirken, bir diğerinde önemsiz olabilir.
Alexey Zimarev

4

CQRS, Depolar için bire bir yerine geçmez, çünkü yalnızca bazı durumlarda yararlı olan karmaşık ve maliyetli bir modeldir.

İşte Udi Dahan'ın liyakat ile söyleyecekleri:

CQRS'yi (ve Etkinlik Kaynaklarını da) kullanan çoğu kişi bunu yapmamalıydı.

[...]

CQRS'yi çevrimiçi olarak göreceğiniz çoğu örnek uygulamanın mimari olarak yanlış olduğunu söylediğim için üzgünüm. Ayrıca sizi varlık tarzı bir toplu kök CQRS modeline yönlendiren çerçevelere karşı da son derece dikkatli olurum.

( kaynak )

Martin Fowler:

[...] CQRS kullanma konusunda çok dikkatli olmalısınız . Birçok bilgi sistemi, okunduğu gibi güncellenen bir bilgi tabanı kavramına iyi uyum sağlar, böyle bir sisteme CQRS eklemek önemli bir karmaşıklık yaratabilir.

( kaynak )

Sonunda Greg Young:

CQRS mimari desen olarak adlandırılabilir.

[...]

Bu, çoğu mimari desenin her yere uygulanmasının iyi olmadığını anlamak için çok önemlidir. Mimari bir kılavuzda mimari desenler görürseniz muhtemelen bir probleminiz var

[...]

Olay kaynağı kullanan kişilerden gördüğüm en büyük başarısızlık, onu her yerde kullanmaya çalışmaktır.

( kaynak )

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.