Wciąż pamiętam stare dobre czasy repozytoriów. Ale repozytoria z czasem stawały się brzydkie. Następnie CQRS znalazło się w głównym nurcie. Byli mili, byli powiewem świeżego powietrza. Ale ostatnio wielokrotnie zadawałem sobie pytanie, dlaczego nie zachowuję logiki w metodzie Action Controller (szczególnie w Web Api, gdzie akcja jest rodzajem programu obsługi poleceń / zapytań).
Wcześniej miałem na to wyraźną odpowiedź: robię to w celu testowania, ponieważ ciężko jest przetestować kontroler z tymi wszystkimi niemożliwymi do wyrzucenia singletonami i ogólnie brzydką infrastrukturą ASP.NET. Ale czasy się zmieniły, a klasy infrastruktury ASP.NET są obecnie znacznie bardziej przyjazne dla testów jednostkowych (szczególnie w ASP.NET Core).
Oto typowe wywołanie WebApi: dodano polecenie i klienci SignalR zostali o tym powiadomieni:
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);
}
}
Mogę z łatwością przeprowadzić test jednostkowy / wykpić to. Co więcej, dzięki OWIN mogę skonfigurować lokalne serwery WebApi i SignalR i wykonać test integracji (a przy okazji całkiem szybki).
Ostatnio odczuwałem coraz mniejszą motywację do tworzenia nieporęcznych programów obsługi poleceń / zapytań i zwykle utrzymuję kod w działaniach interfejsu API sieci Web. Robię wyjątek tylko wtedy, gdy logika się powtarza lub jest naprawdę skomplikowana i chcę ją odizolować. Ale nie jestem pewien, czy robię tutaj właściwą rzecz.
Jakie jest najbardziej rozsądne podejście do zarządzania logiką w typowej nowoczesnej aplikacji ASP.NET? Kiedy uzasadnione jest przeniesienie kodu do programów obsługi poleceń i zapytań? Czy są jakieś lepsze wzory?
Aktualizacja. Znalazłem ten artykuł o podejściu DDD-lite. Wygląda więc na to, że moje podejście do przenoszenia skomplikowanych części kodu do programów obsługi poleceń / zapytań można nazwać CQRS-lite.
Odpowiedzi:
Czy CQRS jest stosunkowo skomplikowanym i kosztownym wzorcem? Tak.
Czy to nadmierna inżynieria? Absolutnie nie.
W oryginalnym artykule, w którym Martin Fowler mówi o CQRS , można zobaczyć wiele ostrzeżeń o nieużywaniu CQRS, jeśli nie ma to zastosowania:
Moje podkreślenie powyżej.
Jeśli twoja aplikacja używa CQRS do wszystkiego, to nie CQRS jest nadmiernie inżynieryjne, to twoja aplikacja. Jest to doskonały wzór do rozwiązania niektórych specyficznych problemów, zwłaszcza aplikacji o wysokiej wydajności / dużej objętości, w których współbieżność zapisu może być poważnym problemem.
I może to nie być cała aplikacja, ale tylko niewielka jej część.
Żywy przykład z mojej pracy: stosujemy CQRS w systemie wprowadzania zamówień, w którym nie możemy stracić żadnych zamówień, i mamy skoki, w których tysiące zamówień przychodzą w tym samym czasie z różnych źródeł, w określonych godzinach. CQRS pomógł nam utrzymać system przy życiu i szybko reagować, jednocześnie pozwalając nam dobrze skalować systemy zaplecza w celu szybszego przetwarzania tych zamówień w razie potrzeby (więcej serwerów zaplecza) i wolniej / taniej, gdy nie są potrzebne.
CQRS jest idealny dla problemu, w którym kilku aktorów współpracuje w tym samym zestawie danych lub pisze do tego samego zasobu.
Poza tym, rozłożenie wzoru wykonanego w celu rozwiązania jednego problemu na wszystkie twoje problemy po prostu stworzy ci więcej problemów.
Inne przydatne linki:
http://udidahan.com/2011/04/22/when-to-avoid-cqrs/
http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/
źródło
CQRS nie zastępuje repozytoriów jeden do jednego, właśnie dlatego, że jest złożonym, kosztownym wzorcem, który jest użyteczny tylko w niektórych przypadkach.
Oto, co zasługuje Udi Dahan:
( źródło )
Martin Fowler:
( źródło )
Wreszcie Greg Young:
( źródło )
źródło