yet another CQS thread ;-)

4 views
Skip to first unread message

Erich Eichinger

unread,
Nov 26, 2009, 4:30:06 AM11/26/09
to altn...@googlegroups.com
Hi,

wir hatten ja bereits ein paar Diskussionen zu dem Thema. Gestern war ich hier in Bergen auf einer NUG Session und hatte das Vergnügen, einen Talk von Mark Nijhof zu sehen. Zumindest für mich klärt das sehr viel, wie CQS in die Architektur paßt. Wer's nicht kennt, er hat seine Gedanken auf seinem Blog gepostet (imho besser als sein Vortrag *g*) und auch recht umfangreichen Beispielcode auf GitHub gestellt:

http://elegantcode.com/2009/11/11/cqrs-la-greg-young/
http://elegantcode.com/2009/11/20/cqrs-the-domain-events/

und es gibt auch einen E-VAN Talk von ihm:
http://elegantcode.com/2009/11/19/recording-of-my-e-van-presentation-about-cqrs/

lg,
Erich

p.s.: In eigener Sache: Danke an die höhere Macht, die mich auf die NNUG Bergen aufmerksam gemacht hat ;-)

Ralf Westphal

unread,
Nov 27, 2009, 6:00:03 AM11/27/09
to altnetde
Danke für die Links. Das sieht interessant aus.

Ich hab in letzter Zeit auch immer mal wieder über CQS nachgedacht.
Mein derzeitiger Meinungsstand:

-Commands sind Commands - sie ändern den Zustand einer
Funktionseinheit. Der muss gar nicht unbedingt in ihr liegen (Felder
eines Objektes), sondern kann auch aus Dateien auf der Platte
bestehen. Commands liefern kein Ergebnis zurück.

-Queries lohnen der differenzierteren Betrachtung. Sie greifen auf
Funktionseinheitzustand nur lesend zu und liefern ein Resultat. Ich
finde jedoch, dass zwei Arten von Queries zu unterscheiden sind:

-- Projektionen, Selektionen oder allgm Views: Ein View liefert vor
allem den Zustand der Funktionseinheit in irgendeiner Form zurück. Er
mag angereichert sein durch Angaben von außen, aber es geht um den FE
Zustand. Typisches Beispiel: IEnum<Customer> GetCustomersByCity(string
city)

-- Transformationen: Sie liefern andere Daten zurück, die allerdings
unter Zuhilfenahme des Zustands ermittelt werden. Beispiel:
IEnum<string> FindSpellingErrors(string text) - der text wird unter
Zuhilfenahme eines internen Verzeichnisses korrekter Wörter
analysiert. Zurückgeliefert werden aber nicht Zustandsdaten, sondern
Teile des hineingereichten Textes.

Zusätzlich scheint mir noch sinnvoll, non-CQ ins Bild zu bringen. Was
ist, wenn gar kein Zustand im Spiel ist? Dann ist eine
Funktionseinheit eine Funktion. Deren Aufruf liefert bei gleichem
Input immer denselben Output. Für mich ist also aus CQS inzw CQFS
geworden.

-Ralf

On 26 Nov., 10:30, "Erich Eichinger" <eeichin...@gmail.com> wrote:
> Hi,
>
> wir hatten ja bereits ein paar Diskussionen zu dem Thema. Gestern war ich hier in Bergen auf einer NUG Session und hatte das Vergnügen, einen Talk von Mark Nijhof zu sehen. Zumindest für mich klärt das sehr viel, wie CQS in die Architektur paßt. Wer's nicht kennt, er hat seine Gedanken auf seinem Blog gepostet (imho besser als sein Vortrag *g*) und auch recht umfangreichen Beispielcode auf GitHub gestellt:
>
> http://elegantcode.com/2009/11/11/cqrs-la-greg-young/http://elegantcode.com/2009/11/20/cqrs-the-domain-events/
>
> und es gibt auch einen E-VAN Talk von ihm:http://elegantcode.com/2009/11/19/recording-of-my-e-van-presentation-...

Björn Rochel

unread,
Nov 30, 2009, 3:49:10 PM11/30/09
to altn...@googlegroups.com
Cool,

danke für den Hinweis. Da werde ich sicher ein wenig Zeit mit verbringen.

Auf der TechEd hatte ich die Gelegenheit noch mal Udi Dahan zu dem Thema zu hören und auch ein paar Fragen loszuwerden.

Was ich persönlich recht interessant fand ist Folgendes:

  • Mittlerweile mappt Udi Screens oft 1 zu 1 auf Datenbanktabellen in seiner Query-Db. Das heisst für jeden Screen in der App gibts tatsächlich auch eine Db-Tabelle.

  • Der Begriff ViewModel ist auf dem Weg zum neuen "Service" zu werden. Jedenfalls meint Udi nicht MVVM, wenn er ViewModel sagt. Interessanterweise unterscheidet er auch zwischen ViewModels (read only) und EditModels (aus denen dann Commands generiert werden). Ja richtig gelesen da ist noch ein Mappingschritt drin.

  • Irgendwie hatte ich immer die Idee das Commands clever aus dem ViewModel (oder jetzt EditModel) abgeleitet werden müssten. Das ist aber gar nicht der Fall. Zumindest macht Udi das nicht. Da ist ganz trivialer, handcoded Plumbing - Code am Werk.

  • CQRS ist zu einem sehr, sehr grossen Teil auch UI Design. Ich meine hier mal zur Abwechlung nicht Patterns, sondern die tatsächliche UX. Screens sind im Idealfall so ausgelegt, dass man mit einer Nachricht ala "Auftrag aufgegeben. In kürze erhalten sie eine Bestätigung" eine Userinteraktion abschließen kann. Ebenfalls sind sie idealerweise von begrenztem Scope. Also eher ChangeCustomerAddressScreen statt ChangeCustomerDataScreen. Je mehr man davon abweicht desto schwieriger ist es ein reines CQRS System zu gestallten . . .

Ganz verdaut habe ich Udis antworten noch nicht. Er hat mir aber noch mal eine weitere interessante Perspektive zum Nachdenken mit auf den Weg gegeben.

VG
Björn

Erich Eichinger

unread,
Nov 30, 2009, 4:35:44 PM11/30/09
to altn...@googlegroups.com
Find ich gut - hier scheinen sich die Geister wohl halbwegs einig zu sein...

> Mittlerweile mappt Udi Screens oft 1 zu 1 auf Datenbanktabellen in seiner Query-Db. Das heisst für jeden Screen in der App gibts tatsächlich auch eine Db-Tabelle.

genau das ist es, was mich an CQRS als Architekturkonzept so reizt. Ich hab immer damit gekämpft, es im Domänenmodell sowohl dem Editscreen als auch der Listenanzeige recht zu machen. Und da spießen sich einfach immer wieder die Bedürfnisse und Concerns unterwandern die Domäne, die dort gar nichts zu suchen haben.

Wenn du dir Mark Nijhof's Grafiken in http://elegantcode.com/2009/11/11/cqrs-la-greg-young/ ansiehst, dann trennt er hier auch strikt zwischen "Edit" und "View" "Bereichen". In meiner Emailkonversation mit ihm hat er explizit davon Abstand genommen, es als 2 getrennte "Bounded Contexts" zu bezeichnen und mich auf http://dddstepbystep.com/wikis/ddd/blog-posts-on-ddd.aspx verwiesen. Dort wird allerdings doch wieder von 2 getrennten Kontexten gesprochen. Aber ich lasse hier die Puristen streiten, der wichtige Punkte denke ich ist, den Bereich, der für die Verarbeitung und Manipulation der Daten zuständig ist in einer klaren, verständlichen Sprache zu modellieren (UL), das Anzeigen der Daten jedoch kann mittels reiner DTOs oder in komplexeren Fällen auch mit VOs (btw, guter Beitrag zu Value Objects: http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson) erfolgen - hier ist wenig bis keine Logik erforderlich.

Diese Idee resultiert für mich letztlich in 2 wesentlichen Entscheidungen, die zu treffen sind:

1) ist meine Domain und die Problemstellung komplex genug, um eine Event-getriebene Lösung wie sie Nijhof in seinem Samplecode vorschlägt (in seinem Fall überdies sogar asynchron - höre ich da Ralf jubeln?) zu rechtfertigen oder verwende ich direkt eine stinknormale Datenbank, in die die Aggregate gespeichert werden

2) Wieviele Views lasse ich in der Anwendung zu? Ich denke hier sollte dann doch eine gewisse Konsolidierung stattfinden - für jeden Screen ein eigenes Datenmodell + ev. sogar noch eine Datenbankview oder im Extremfall von Nijhof sogar eigene Commandeventhandler, die das Event Modulspezifisch verarbeiten und in eine Moduleigene Datenbank ablegen (womit wir mit Ausnahme der fehlenden Logik imho schon sehr nah an einem Bounded Context wären), daß ist dann vielleicht doch zuviel unkontrollierbarer Wildwuchs.

Alles in allem gefällt mir aber die Idee, erst mal aus dem Input ein Command zu erzeugen, daß dann in weiterer Folge eine Änderung des Applikationszustands bewirkt. Dadurch habe ich eine gewisse Freiheit, erstmal das Command aufzugreifen aber direkt und synchron meine Zustandsobjekte in die Datenbank zu speichern und später - falls nötig - die Erzeugung und Verarbeitung des Commandevents zeitlich zu entkoppeln oder gar auf Nijhof's Lösung, nur die Events zu speichern und gar kein eigenes Datenmodell hinter der "Edit"-Domain zu halten, zurückzugreifen. Die Events können sogar über Maschinengrenzen hinweg verschickt werden, womit sich dann Systemteile auch auf andere Maschinen auslagern lassen. Insgesamt halte ich diese Architektur also für gut geeignet, von relativ klein bis ziemlich groß über eine große Bandbreite an Systemkomplexität zu skalieren.

Nun bleibt nur noch abzuwarten, daß jemand anders als Udi Dahan und Greg Young eine solche Architektur tatsächlich umsetzen. Nijhof z.B. musste mir nämlich auf Rückfrage gestehen, noch nie ein solches System tatsächlich "in the wild" realisiert zu haben.

-Erich

Erich Eichinger

unread,
Nov 30, 2009, 4:45:49 PM11/30/09
to altn...@googlegroups.com
> -- Transformationen: Sie liefern andere Daten zurück, die allerdings
> unter Zuhilfenahme des Zustands ermittelt werden. Beispiel:
> IEnum<string> FindSpellingErrors(string text)

Also wenn ich Nijhof hier richtig verstanden habe, dann würde diese Transformation bereits von einem Commandeventhandler, als bereits bei der Verarbeitung des Commands in dem entsprechenden Modul durchgeführt und die aufbereiteten Daten in die DB gespeichert werden. Damit bleibt letztlich wieder nur eine "dumme" View übrig, die sich durch sehr einfache Queries lösen lässt. Ergibt meistens(!) wohl auch mehr Sinn, diese Berechnung beim Speichern des Textes durchzuführen und nicht jedesmal bei der Anzeige.

Die gesamte CQRS Architektur macht aber natürlich nur Sinn, wenn wir von 90% Lese+Anzeigeoperationen vs. 10% Datenmanipulation reden. Im umgekehrten Fall wird dieser Ansatz wohl ziemlich scheitern.

-Erich

> -----Original Message-----
> From: altn...@googlegroups.com [mailto:altn...@googlegroups.com] On
> Behalf Of Ralf Westphal
> Sent: Friday, November 27, 2009 12:00 PM
> To: altnetde
> Subject: [altnetde] Re: yet another CQS thread ;-)
>
>

Björn Rochel

unread,
Dec 9, 2009, 4:53:58 PM12/9/09
to altnetde
Hi,

Udi hat sich mal wieder zu dem Thema geäussert:

http://www.udidahan.com/2009/12/09/clarified-cqrs/

Sehr lesenswert . . .

VG
Björn

Erich Eichinger

unread,
Dec 9, 2009, 6:38:27 PM12/9/09
to altn...@googlegroups.com

also irgendwie kann ich mir ein Grinsen ja nicht verkneifen...

 

 

 

 

> -----Original Message-----

> From: altn...@googlegroups.com [mailto:altn...@googlegroups.com] On

> Behalf Of Björn Rochel

> Sent: Wednesday, December 09, 2009 10:54 PM

> To: altnetde

> Subject: [altnetde] Re: yet another CQS thread ;-)

>

>

> Hi,

Björn Rochel

unread,
Dec 10, 2009, 11:33:50 AM12/10/09
to altn...@googlegroups.com
Ja, ging mir ähnlich . . .

VG
Björn

Am 09.12.09 schrieb Erich Eichinger <eeich...@gmail.com>:
> also irgendwie kann ich mir ein Grinsen ja nicht verkneifen...
>
>
>
>
>
>
>
>
>
>
>
>> -----Original Message-----
>
>> From: altn...@googlegroups.com [mailto:altn...@googlegroups.com] On
>
>> Behalf Of Björn Rochel
>
>> Sent: Wednesday, December 09, 2009 10:54 PM
>
>> To: altnetde
>
>> Subject: [altnetde] Re: yet another CQS thread ;-)
>
>>
>
>>
>
>> Hi,
>
>>
>
>> Udi hat sich mal wieder zu dem Thema geäussert:
>
>>
>
>> http://www.udidahan.com/2009/12/09/clarified-cqrs/
>
>>
>
>> Sehr lesenswert . . .
>
>>
>
>> VG
>
>> Björn
>
>>
>
> >
>

--
Gesendet von meinem Mobilgerät

Steve Wagner

unread,
Dec 10, 2009, 3:47:41 PM12/10/09
to altn...@googlegroups.com
Ich saß auch in dem talk von Udi. Das ganze klang sehr interessant, aber
ich würde auch gern erstmal ne Beispiel-Implementierung sehen.

Die ganze Screen 1:1 mappen kling ja ganz nett wenn man reine Tabellen
anzeigen will, aber die meisten Applikationen die mir einfallen zeigen
die Daten eh direkt in den Eingabemasken an.

Erich Eichinger schrieb:

Erich Eichinger

unread,
Dec 11, 2009, 4:38:41 AM12/11/09
to altn...@googlegroups.com
Hast du dir Mark Nijhof's Code schon angesehen? Ist zwar anfangs - wie ich finde - gewöhnungsbedürftig, aber nach einer Weile wird klar, wie der Hase läuft.

> zeigen die Daten eh direkt in den Eingabemasken an.
nun ja, aber irgendwoher müssen die Daten kommen und sie müssen irgendwie strukturiert sein. Meinst du sowas wie Oracle Forms (ja, ich weiß, hoffnungslos outdatet - aber immer noch bittere Realität in vielen Fällen ;-)).

Auf einem abstrakten Level dreht sich die ganze Sache ja um die Trennung von modifizierenden Aktionen, die auch gewisse Logik erfordern und dem "dummen" Anzeigen der Daten.

Wenn es nur um Datensatz raus, Feldinhalt ändern, Datensatz rein geht, dann ist CQRS ev. nicht der richtige Ansatz.

-Erich

> -----Original Message-----
> From: altn...@googlegroups.com [mailto:altn...@googlegroups.com] On
> Behalf Of Steve Wagner
> Sent: Thursday, December 10, 2009 9:48 PM
> To: altn...@googlegroups.com
> Subject: [altnetde] Re: yet another CQS thread ;-)
>
>
> --~--~---------~--~----~------------~-------~--~----~
> Sie erhalten diese Nachricht, weil Sie Mitglied sind von Google Groups-
> Gruppe "altnetde".
> Für das Erstellen von Beiträgen in dieser Gruppe senden Sie eine E-
> Mail
> an altn...@googlegroups.com
> Um sich von dieser Gruppe abzumelden, senden Sie eine E-Mail an
> altnetde+u...@googlegroups.com
> Weitere Optionen finden Sie in dieser Gruppe unter
> http://groups.google.com/group/altnetde?hl=de
> -~----------~----~----~----~------~----~------~--~---

Markus Zywitza

unread,
Dec 12, 2009, 6:54:34 AM12/12/09
to altnetde
Am 11. Dezember 2009 10:38 schrieb Erich Eichinger <eeich...@gmail.com>:
> Auf einem abstrakten Level dreht sich die ganze Sache ja um die Trennung von modifizierenden Aktionen, die auch gewisse Logik erfordern und dem "dummen" Anzeigen der Daten.
>
> Wenn es nur um Datensatz raus, Feldinhalt ändern, Datensatz rein geht, dann ist CQRS ev. nicht der richtige Ansatz.

Na ja, die meisten Benutzer sind das Thema Daten raus, anzeigen,
ändern, rein so gewöhnt, dass sie sich nichts anderes vorstellen
können. Wer nur einen Hammer hat, für den ist hat alles ein Nagel...
Das Ergebnis ist, dass die User auf Biegen und Brechen nur
Eingabemasken wollen. Ich bastel dann meistens ein Access-Projekt (in
der Regel codefrei) und warte dann auf die ersten Beschwerden, was
denn "einfacher" gehen sollte. Dann kann man sich mit den Benutzern
auch über User Stories unterhalten und dass es auch mehr gibt als
Eingabemasken.

-Markus

Alexander Zeitler

unread,
Dec 13, 2009, 2:47:12 PM12/13/09
to altn...@googlegroups.com
Hi,

es gibt auch ein Recording von Mark Nijhofs E-VAN zu CQRS:
http://vimeo.com/7838858

Alex
--~--~---------~--~----~------------~-------~--~----~
Sie erhalten diese Nachricht, weil Sie Mitglied sind von Google Groups-Gruppe "altnetde".

Sebastian Jancke

unread,
Dec 14, 2009, 3:18:53 AM12/14/09
to altn...@googlegroups.com
So eine "aufgabenbezogene" GUI ist auch viel konformer zur Usability Iso-Norm. Das ist wohl die andere Seite der Medaille, das solch eine Architektur besser skaliert (wenn man es braucht!).

-Sebastian

Erich Eichinger

unread,
Dec 14, 2009, 3:44:06 AM12/14/09
to altn...@googlegroups.com

ich probier diese C/Q Unterscheidung grad in meinem Projekt aus. Funktioniert soweit super, weil es für das Erstellen der GUIs nur wenig Wissen braucht und man tatsächlich die Views (oder einen Satz von Views im Fall eines logische Prozesses) weitgehend unabhängig voneinander nach "Kochrezept" entwickeln kann. Sieht in meinem Fall ganz einfach aus

 

Database View(s)

    |

Data Access Object  + simples Row-Mapping auf DTOs

    |

Controller

    |

View(s)

 

Wie man sieht verwende ich kein Eventsourcing und auch die DB ist geshared zwischen Write/Read, dazu ist mir die App zu klein, um diesen Aufwand tatsächlich zu rechtfertigen. Aber schon mit diesem minimalen Ansatz arbeitet es sich recht fein, weil man durch die fehlenden Code-Abhängigkeiten ziemlich flexibel bei der Umsetzung ist.

 

-Erich

 

--

Sie haben diese Nachricht erhalten, da Sie der Google Groups-Gruppe altnetde beigetreten sind.
Wenn Sie Nachrichten in dieser Gruppe posten möchten, senden Sie eine E-Mail an altn...@googlegroups.com.
Wenn Sie aus dieser Gruppe austreten möchten, senden Sie eine E-Mail an altnetde+u...@googlegroups.com.
Besuchen Sie die Gruppe unter http://groups.google.com/group/altnetde?hl=de, um weitere Optionen zu erhalten.

Sebastian Jancke

unread,
Dec 14, 2009, 4:30:04 AM12/14/09
to altn...@googlegroups.com
Erich,

das klingt gut. Bin gespannt welche Erfahrungen du sammelst. Bei Zeiten (ArchNet10 ??) kann ich vielleicht mal über unsere Erfahrung bis dahin berichten.

-sj
Reply all
Reply to author
Forward
0 new messages