25. Newsletter Double-Opt-In – User Stories
• Als User kann ich meine E-Mail Adresse anmelden, um den Newsletter zu
erhalten.
• Als User erhalte ich eine E-Mail nach Anmeldung, um diese zu bestätigen.
• Als User kann ich die Bestätigungs-E-Mail erneut anfordern, um meine E-Mail
Adresse zu bestätigen.
• Als User kann ich meine E-Mail Adresse bestätigen, um die Anmeldung
abzuschließen.
• Als User erhalte ich eine Welcome E-Mail, sodass ich über den Abschluss der
Anmeldung informiert bin.
26. Client
CQRS + SOA – Our best practice
Query
Handler
Reposi-
tory
View
GET
POST
GetRequest
Handler
PostRequest
Handler
Called dynamically
Command
Handler
ReadService
Query
WriteService
Command
Called explicitly
27. Empfehlungen
• Einführung in CQRS
http://martinfowler.com/bliki/CQRS.html
• MVC in Webanwendungen
https://entwickler.de/online/php/model-view-controller-in-webanwendungen-
138762.html
• Wartbares Design dank CQRS
https://entwickler.de/online/development/wartbares-design-dank-cqrs-
139615.html
Vorstellen Holger – CIO FORTUNEGLOBE u. HEAD of FORTUNE SOLUTIONS
Vorstellen mich
Phpind.de
Warum CQRS?
Suche nach Alternativen zum MVC nach unzähligen Legacy-Anwendungen mit Zend, Symfony und eigenem MVC-Framework
Schmerzen beim Refactoring und dem Versuch andere Ansätze zu verknüpfen
Für uns die größte Annäherung an das HTTP-Protokoll und die beste Art andere Ansätzen wie DDD, EventSourcing oder SOA anzuknüpfen
Was zeigen wir?
Kritische Betrachtung des MVC-Patterns in Webanwendungen
Theoretische Vorstellung CQRS als Alternative
Live Coding
1979 formuliert norweg. Informatiker den Begriff Model-View-Controller
Mehr als 40 Jahre alt und ursprünglich für Desktopanwendungen
Frage stellen: Wie funktioniert das MVC ursprünglich?
Klassischer Anwendungsfall sind Multiple Document-Interface-Applikationen
Nutzer kann mehrere Fenster (Views) gleichzeitig öffnen
Wenn sich Model ändert, müssen alle Views aktualisiert werden
Somit wird Nutzer wiederholtes hin-und herblättern zw. 2 Fenstern erspart
Dies passiert über eine Subject-Observer-Beziehung, bei dem alle Objekte schon fest verbunden sind
View 1 -> Änderung an Controller -> ändert Zustand des Models -> Views werden aktualisiert
Problem 1: Webanwendungen sind Client-Server-Anwendungen -> Trennung durch Systemgrenze
Problem 2: Webanwendungen sind Request-Basiert -> Objektgraph zum Zeitpunkt der Änderung noch gar nicht vorhanden -> Wir müssen erstmal überlegen wie wir die Objekte erzeugen
Was passiert nun im Web - Klick
Klick auf Button im Browser
HTTP-Request wird an Server gesendet -> Controller soll darauf angemessen reagieren
Problem: Welcher Controller überhaupt. -> Was tun wir? – Routing! -> Frameworks machen das über sog. FrontController -> dieser führt erst das Routing durch und ruft dann den Controller auf
Klick
Controller muss nun mit einem Model sprechen – aber welches Model?
Aus dem Request muss erstmal herausgefunden werden, welches Model geladen werden muss – machen die Controller
Im klass. MVC ist es gar nicht vorgesehen entscheiden zu müssen, welches Model geladen werden muss
Im Web muss der Controller aber diese Verantwortung übernehmen -> fraglich ob es sinnvoll ist die Verantwortlichkeit hineinzudichten
Klick
Nun müsste Model Views über Änderung informieren
Auf Server existieren die Views nur als HTML String
Erst beim Rendern im Client bekommen sie echtes Verhalten
View bekommt nun eine andere Bedeutung – statt von einem GUI-Element sprechen wir nun von ganzen HTML-Seiten
Und Client kann nur Daten per HTTP abrufen -> Subject-Observer-Muster kann nicht sinnvoll umgesetzt werden
Klick
Also was tun wir?
Wir informieren den Controller über die Zustandsänderung
Controller soll nun entscheiden welche View dargestellt werden soll, obwohl man das gar nicht immer genau wissen kann
POST vs. GET und darf User eine Seite überhaupt sehen, ohne eingeloggt zu sein (Redirect auf Loginseite)
Ergebnis: Controller hat plötzlich 2 Aufgaben: 1 soll „Kommando“ an die Applikation verarbeiten und 2 er soll entscheiden welche View anzuzeigen ist
Verstoss gegen Single-Responsibility-Konzept!
Probleme zusammenfassen
Trennung durch Systemgrenze – wegen Client-Server-Architektur
Kommunikation Requestbasiert durch HTTP
Subject-Observer-Beziehung kann nicht sinnvoll umgesetzt werden, da Model nicht mit View kommunizieren kann
Verstoss gegen Single-Responsibility-Prinzip, da Controller mehr als 1 Aufgabe hat
Controller verantwortlich für das Laden des Models
Fragen bis hier hin?
4 Probleme bewerten
Systemgrenze können wir nicht ändern
HTTP-Request können wir auch nicht ändern
Aber wir können ihn in den Mittelpunkt rücken
Subject-Observer entfällt
Bleibt noch Single-Responsibility
Zentrales Prinzip für das Design wartbarer Software
Irgendjemand muss die Models kennen, aber muss es der Controller sein
Somit rücken der HTTP-Request und das Single-Responsibility Prinzip in den Fokus
Schauen wir uns das genauer an
GET-Request beim Seitenaufruf bspw. durch Linkklick
GET-Request ist ein reiner Lesezugriff
Sagen wir GET-Request wird an einen Read Controller delegiert
Read Controller lädt Model und fragt Daten ab, rendert View
POST-Requests beim Absenden von Formularen
POST-Requests sind Schreibzugriffe und ändern den Zustand einer Applikation
Problem: Zustand des Models wurde geändert
Controller darf nur schreiben – was nun?
Senden Redirect auf den entsprechenden Read-Controller
Redirect ist eine gültige HTTP-Response in der ein Location Header gesendet wird
Client wird angewiesen einen neuen GET-Request zu senden
Was haben wir gewonnen?
Wir behandeln die unterschiedlichen HTTP-Requests getrennt
HTT-Protokoll wird besser abgebildet
Was war jetzt mit Single-Responsibility?
Schauen wir uns den Controller nochmal an
Aufgaben des Controllers -Kommando entgegennehmen - Model laden - Entscheiden welche View gerendert wird
Kommando behandeln bleibt die zentrale Aufgabe
Entscheidung View entfällt, da immer nur 1 möglich
Bleibt als 2. Aufgabe das Laden des Models
Was wäre wenn wir diese Aufgabe delegieren?
Schalten wir nach vor den Controller einen Handler der den Request verarbeitet
Der Handler delegiert nun das Laden des Models jetzt an den Controller
Somit hat der Controller nur noch 1 Aufgabe
Super alle Probleme gelöst
Schauen wir uns unsere Lösung aber nochmal an
Wenn wir sagen, dass GET-Request Lesebefehle also Queries sind
Und das POST-Requests Schreibbefehle, also Commands sind
Und wir das in unsere Benamung übernehmen, dann - Klick
Bekommen wir CQRS Command Query Responsibilty Segregation
Also Trennung zwischen Lese- und Schreibzugriffen
Außerdem Trennung zwischen Applikations- und Anzeigelogik zu trennen
man sihet hier auch, wie man CQRS auch in bestehende MVC Anwendungen integrieren kann
Indem man die Lese und Schreibzugriffe trennt und dem Controller „falsche“ Aufgaben nimmt
Wie nun die Applikationslogik und die Businesslogik implementiert werden beantwortet CQRS nicht
Gängige MVC-Frameworks tun das auch nicht
Aber wie es in der Praxis aussehen kann und warum man mit CQRS vieles geschenkt bekommt zeigt euch Holger im - Klick
Artikel von Martin Fowler und Stefan Priebsch sehr ans Herz gelegt
RequestHandler werden vom Framework dynamisch aufgerufen
Query / Command schaffen konkretes Interface für die Request-Daten
Services kapseln die Business-Logik und sprechen mit dem Model /
Query-/Command Handler verarbeiten die Ergebnisse der Service-Aufrufe zu einer Antwort
Services sind komplett austauschbar ohne das Request / Response Handling anfassen zu müssen!
Artikel von Martin Fowler und Stefan Priebsch sehr ans Herz gelegt
Wer schonmal anfangen will – IceHawk Framework
Vielen Dank
Slides auf unserem Blog phpind.de und auf slideshare
Verlinkung auch auf der UG-Seite
Beispiel-Code auf GitHub