Laden...

CQRS Pattern, QueryHandler Design

Erstellt von Olii vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.980 Views
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 5 Jahren
CQRS Pattern, QueryHandler Design

Hallo liebe Forum User,

ich hatte vor kurzem schon mal einen Post zum Repository Pattern gemacht und sehr liebe und Hilfreiche Antworten bekommen.

Dort wurde unter anderem dann das CQRS Pattern erwähnt was mich neugierig gemacht hat.
Also habe ich mich am CQRS Pattern versucht.

Ich bin dieser Anleitung gefolgt:
Simple SQRS

Ich habe mal versucht den Teil für die Queries zu implementieren und habe dabei versucht Probleme mit meinem eigenen Wissen zu lösen.

Zum Beispiel wurde im Beispiel eine static classe für die Handler verwendet die ich durch ein Interface und eine normale Klasse getauscht habe um dependency injection zu ermöglichen.

Das funktioniert alles auch beim testen, aber ob das so richtig umgesetzt ist im Sinne von CQRS und dem Event Sourcing Pattern, weiß ich leider nicht. Ich würde das gerne richtig lernen aber alle Beispiele im Internet weichen stark von einander ab, so das ich gerade keinen festen Boden unter mir habe und irgendwie nicht vor und nicht zurück komme.

Falls jemand etwas Zeit und Lust hat mir zu helfen, habe ich das kleine Projekt auf GitHub hochgeladen. Es ist sehr schlang und beinhaltet nicht viel Code.

Wichtig sind nur die Ordner Controllers, Models und Domain.

Hier ist das Repository:
CQRS Pattern

Ich danke jetzt schon einmal für Antworten und freue mich wenn viel kritisiert wird, damit ich mich verbessern kann 😃

16.834 Beiträge seit 2008
vor 5 Jahren

Finde das Beispiel nicht gut - oder sehr sehr einfach; keine richtige Übersichtlichkeit, nicht vollständig.

Das geht deutlich einfacher und übersichtlicher, zB mit MediatR.
(M)Ein Beispiel dazu: https://github.com/BenjaminAbt/2018-Talks-ModernApiDevelopment/tree/master/src/Common.Engine
Verwende ich produktiv und in Talks. Würde nie CQRS ohne Framework drum herum umsetzen (wollen).

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 5 Jahren

Danke erstmal für deine Antwort Abt.

Schade ich hatte gehofft das Beispiel kommt dem sehr nahe, habe aber schon vermutet dass das wohl zu einfach wäre 😄.

Okey also wäre es keine gute Idee alles selber aufzubauen. Dann werde ich mir MediatR angucken. Danke für dein Beispiel, sieht auf den ersten Blick sehr übersichtlich aus. Die Struktur ist da aber nicht drin wenn ich richtig sehe oder? Die wird dann vermutlich durch MediatR angelegt.

Ich werde mir das morgen früh auf jeden Fall mit frischen Kopf ansehen.

Ich habe gerade mal dieses Tutorial zu MediatR und CQRS gefunden. Ist komplexer als das andere. Ich hoffe das dieses dem richtigen Weg näher kommt.

MediatR und CQRS Pattern

Wenn ich dich (ich Du'ze jetzt einfach mal) mal etwas persönlicheres Fragen darf, wie machst du das wenn du an so neue Sachen ran gehst? Tutorials? Oder doch try and error? Ich möchte gerne an können so viel wie möglich wachsen um auch anderen mal eine Hilfe zu sein ._.

Bei so einem Thema das so viele Ansätze hat und oder Möglichkeiten (zumindest wirkt es auf mich so), ist es für ein neuen sehr schwer überhaupt einen Durchblick zu bekommen.

16.834 Beiträge seit 2008
vor 5 Jahren

Danke für dein Beispiel, sieht auf den ersten Blick sehr übersichtlich aus. Die Struktur ist da aber nicht drin wenn ich richtig sehe oder? Die wird dann vermutlich durch MediatR angelegt.

Es ist alles drin; es ist ein funktionales, aus der realität stammendes Beispiel.
MediatR ist aber ein Framework, das die gesamte Infrastruktur liefert - Du musst Dich nur im Commands, Queries und deren Handler anschauen.

Wenn Du das Konzept (Handler und Co) selbst übernehmen willst, weil es ein Lernthema ist, dann MediatR nicht verwenden.
Es nimmt die gesamte Infrastruktur von CQRS ab.

Ist komplexer als das andere. Ich hoffe das dieses dem richtigen Weg näher kommt.

CQRS ist ein komplexer Pattern mit relativ viel Overhead; ich verwende ihn schon länger.
Aber wirklich auch für kleine Dinge wird es erst durch Frameworks wie MediatR interessant, da dies die Infrastruktur stabil abnimmt.

Richtig komplex wird es dann wirklich mit Event Sourcing, verteilt über Domänen und Anwendungen; und womöglich dann noch via Process Handling und Saga 😉

Wenn ich dich (ich Du'ze jetzt einfach mal)

Wir duzen hier uns alle.

wie machst du das wenn du an so neue Sachen ran gehst? Tutorials? Oder doch try and error?

Wenn es darum geht ein Konzept zu verstehen, dann orientiere ich mich an Blogs und Vlogs; ich bin kein Buch-Typ.
Und ich lade mir dann durchaus auch Quellcode runter, um potentielle Umsetzungen zu sehen.

Try-und-Error spielt aber natürlich immer eine Rolle in der Software; aber blind drauf los macht auch wenig Sinn.
Das Konzept muss man schon verstanden haben, und dann agil an die Sache: erst klein Anfangen, und dann wachsen.

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 5 Jahren

Guten Morgen,

ich gucke mir gerade dein Beispiel an, mir fällt auf du Benutzt ein GUID als ID in den Models. Das wirkt sich doch sehr negativ auf die Performance aus, wäre ein normal integer Wert nicht besser?

16.834 Beiträge seit 2008
vor 5 Jahren

Das ist ein Märchen, das sich leider immer noch hält.

Eine Guid braucht zwar tendentiell mehr Speicher (4 byte vs 16 byte) - mit der Performance hat das in erster Linie genau null für 99,999% der Anwendungen zutun.
Im Gegensatz zu Int skaliert jedoch eine Guid, weswegen sie in skalierenden Umgebungen auch pflicht bzw. dies die technische Voraussetzung ist.
Dass es wirklich Unterschiede gab (von wenigen, kaum messbaren Prozentwerten) - und das auch nur beim Generieren der Guids - ist schon Jahr(zehnt)e überholt.
Datenbanken wie CosmosDB, MongoDB und Co unterstützen gar kein Int mehr als Key; sondern nur noch UUIDs - und das hat sein Grund.

Daher: nein, ein Int ist pauschal garantiert nicht besser.
Eine Int wird vor allem aufgrund der Human Identification benutzt - nicht wegen irgendeiner Performance.

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 5 Jahren

hmm okey, ich hatte auf StackOverflow geguckt, da waren sich die meisten einig. Aber gut zu wissen. Würdest du GUID's auch als Primär-Schlüssel in einer Datenbanktabelle empfehlen? Bzw. ob es sich im heutigen stand der Dinge lohnt? Zumindest für relativ einfach Abfragen mit wenig JOIN's etc.

Danke übrigens für deine Hilfe. Das ist nicht selbstverständlich und ich weiß das sehr zu schätzen das du mir hilfst mein Unwissen in Wissen umzuwandeln.

16.834 Beiträge seit 2008
vor 5 Jahren

hmm okey, ich hatte auf StackOverflow geguckt, da waren sich die meisten einig.

Dann les aber auch mal, was genau die Performance beeinflusst (das nicht-sequentielle Generieren dieser) und die Performance bei IOps wenns um die Synchronisation großer Datenmengen (weil Key x4).
Das trifft aber auf 99,9999% der Anwendungen gar nicht zu bzw. ist irrelevant.

Würdest du GUID's auch als Primär-Schlüssel in einer Datenbanktabelle empfehlen?

Wie gesagt; viele Datenbanken, die auf große Daten und Performance ausgelegt sind (CosmosDB, MongoDB) erzwingen eine UUID.
UUID ist pauschal nicht schlecht - im Gegenteil. GUID ist First Citizen. Warum sollte ich sie nicht empfehlen? Dafür sind sie da!

Zumindest für relativ einfach Abfragen mit wenig JOIN's etc.

Irrelevant.

Über Performance macht man sich dann maßgeblich Gedanken, wenn es das Konzept oder die Situation erfordert.
Aber hier reden wir von Unterschieden, die wie gesagt für 99,999999999999% aller Anwendungen völlig egal ist.

PS: wenn ich mir die SO Beiträge so ansehe, dann bestätigt das meine Aussage - und es wird oft über alte MSSQL Server (zB Server 2000) sowie eben das nicht-sequentielle Generieren (und die Abhilfe NEWSEQUENTIALID) gesprochen.

Solche Micro-Performance Optimierungen sollte man ganz ganz ganz weit hinten anstellen... premature performance optimization is the root of all evil
Du bohrst hier an der falschen Stelle nach Performance-Optimierungen 😉

Würdest du GUID's auch als Primär-Schlüssel in einer Datenbanktabelle empfehlen?

... ist ingesamt aber die falsche herangehensweise.

Man sucht sich seinen PK nicht nach dem Typ aus. Ein PK ist ein logisches Konstrukt und sollte auch so behandelt werden.
In einer Datenbank, in der ich Seriennummern führe (Produktdatenbank mit über 250 Millionen Produkten) ist der PK ein String - und zwar die Seriennummer.

Wenn Du ein Clustering aufsetzt, dann spielt der Key auch technisch eine Rolle, da hier der Clusteringindex dann schnell sehr groß werden kann.

PS: bitte nicht zum Endlosthema werden lassen.
Hier ging es maßgeblich um CQRS - nicht SQL Performance.

T
2.224 Beiträge seit 2008
vor 5 Jahren

Was die Performance von Guid als PK in der DB angeht, kann ich dir mit Sicherheit sagen, dass diese kein Problem darstellt.

Bei uns nutzen wir für fast alle Tabelle wo es keinen Grund dagegen gibt, Guids als PKs.
Gerade wenn man von schnell wachsenden Tabellen für z.B. GPS oder Belegedaten ausgeht, dann ist die Guid die richtige Wahl.
Hätten wir damals einen anderen PK gewählt, hätten wir z.B. Probleme mit doppelten Daten durch eine Imei die mit gleichen Zeitstempeln Daten mit unterschiedlichen Zuständen liefert.
Gerade bei den Mengen an Belegdaten, die wir in unserer Außendienstlösung verarbeiten müssen, Großkunden mit mehreren Mio. Belegen samt Belegpositionen.
Diese könnte man nicht ohne weiteres mit Auto Inkrement o.ä. sauber verwalten.

Hier laufen bei uns pro Woche mehrere Mio. GPS Datensätze bei unserer GPS Flottenlösung ein, die aus Performance Gründen nach einer Woche auf eine SMB Freigabe geschrieben und dort archiviert werden.
Also im groben ein schon mehr als 10 Jahre alter NoSQL Ansatz der Guid als PK verwendet.
Auch andere Tabellen in der DB verwenden soweit möglich einen Guid PK um eindeutige Keys zu haben.
Wir reden hier von Datenbanken mit einer Gesamtgröße ab 100GB und aufwärts.
Und da haben wir mehr Probleme bei riesigen Joins oder Suchvorgängen wegen der reinen Datenmenge als mit der Guid als PK.

Und das Projekt wird von mir auch seit 10 Jahren entwickelt und wurde erst im April nochmal auf Performance getrimmt.
Und dafür müssten wir nicht mal die DB ändern sondern einfach die vom damals 2008 SQL Server erstellen Datenbankdateien splitten, die Transaktionslogs auslagern und die Temp DBs Dateien auslagern.

Alleine durch Optimierung der Schreib- und Lesevorgänge kann man meist mehr aus der DB holen als veraltete Probleme wie Guids als PK sich den Kopf zu zerbrechen.

Zur aller größten Not bau dir mit einer Express DB einen Testfall und prüf es selbst nach.
Aber der SQL Server hat schon seit 2012 kein Problem mehr mit Guids als PK.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.