divide and conquer - 2 years of cqrs in production

81
DIVIDE AND CONQUER 2 YEARS OF CQRS IN PRODUCTION 30. SEPTEMBER • CODE.TALKS 2016 • HAMBURG HOLGER WOLTERSDORF

Upload: holger-woltersdorf

Post on 21-Jan-2017

466 views

Category:

Software


0 download

TRANSCRIPT

DIVIDEANDCONQUER2 YEARS OF CQRS IN PRODUCTION

30. SEPTEMBER • CODE.TALKS 2016 • HAMBURG

HOLGER WOLTERSDORF

GRÜNDUNGS-MITGLIED DER

phpind.de

HOLGER WOLTERSDORF CIO • FATHER • HUSBAND • PHP DEV WITH ♥

github.com/hollodotme github.com/PHPinDD

@hollodotme @phpindd

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

KLEINE ZEITREISE

3

2014 20162015

MVC vs. CQRS

EINFLÜSSE & GRUNDSÄTZE

Framework 1.0 Framework 2.0

Pitfalls

MVC vs. CQRS

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

5

MODEL VIEW

CONTROLLER (MVC)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

6

๏ WEB-MVC FAQ [fʌk]

๏ Wie viel Logik gehört ins Model?

๏ Ist das Template meine View?

๏ Was kontrolliert ein Controller?

๏ … und was sind eigentlich Helper?

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

7

(eine nicht gänzlich unbekannte PHP Beratungsfirma)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

8

๏ DAS MVC PATTERN

VIEW VIEW

CONTROLLER MODEL

BENUTZER EINGABE

MODIFIZIERT

AKTUALISIERT

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

9

๏ DAS MVC PATTERN

VIEW VIEW

CONTROLLER MODEL

BENUTZER EINGABE

MODIFIZIERT

AKTUALISIERT!

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

10

HTTP ZIEHT EINE NATÜRLICHE GRENZE

ZWISCHEN SERVER UND CLIENT

(…ja, ja Web-Sockets)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

11

DAS MVC-PATTERN LÖST EIN PROBLEM, DAS ES IM WEB

NICHT GIBT.

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

12

๏ NEUE FRAGEN

๏ Warum nicht Lesen und Schreiben trennen?

๏ Wird ein Request kontrolliert oder behandelt?

๏ Wir liefern doch Seiten aus, warum gibt es keine Klasse, die Page heißt?

๏ Sollten Schreibvorgänge Ausgabe produzieren?

๏ Was ist ein Framework?

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

13

COMMAND QUERY

RESPONSIBILITY SEGREGATION

(CQRS)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

14

๏ DAS CQRS PATTERN (respektiert HTTP)

PAGE 1 PAGE 2

REQUESTHANDLER APP STATE

BENUTZER EINGABE

MODIFIZIERT

VORBEREITENPOST

CLIENT / BROWSER

REDIRECT ZU PAGE 2

GET GET

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

15

๏ DAS CQRS PATTERN (respektiert HTTP)

PAGE 1 PAGE 2

REQUESTHANDLER APP STATE

BENUTZER EINGABE

MODIFIZIERT

VORBEREITENPOST

CLIENT / BROWSER

REDIRECT ZU PAGE 2

GET GET

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

16

๏ CQRS REGELN

๏ Ein POST-Request liefert keinen Content aus

๏ Ein POST-Request kann den App-Zustand ändern

๏ Ein POST-Request antwortet mit einem Redirect

๏ Ein GET-Request liefert Content aus

๏ Ein GET-Request darf nicht den App-Zustand ändern

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

17

MOMENT MAL …

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

18

WAS IST DER UNTERSCHIED ZWISCHEN EINER (GUTEN) REST-API

UND EINER WEBSITE?

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

19

๏ REST-API

๏ REST-API ändert Ressourcen durch Schreibbefehle (POST / PUT / PATCH / DELETE)

๏ REST-API verweist auf geänderte Ressourcen (z.B. durch HATEOAS*-Tags)

๏ REST-API liefert Ressourcen im aktuellen Zustand durch Leseanfragen (GET)

๏ REST-API liefert Information über das Vorhandensein von Ressourcen und möglichen Aktionen (HEAD / OPTIONS)

* HATEOAS = Hypermedia As The Engine Of Application State

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

20

๏ WEBSITE

๏ Website ändert den App-State durch Schreibbefehle (POST [/ PUT / PATCH / DELETE])

๏ Website verweist auf geänderte Seiten (REDIRECT)

๏ Website liefert Seiten im aktuellen Zustand durch Leseanfragen (GET)

๏ Website liefert Information über das Vorhandensein von Seiten und möglichen Aktionen (HEAD / OPTIONS)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

21

๏ REST-API != WEBSITE

๏ Website hat einen "flüchtigen" Zustand (Session)

๏ Website liefert HTML statt XML/JSON/etc. aus

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

22

SUPRISE, SUPRISE!

GUTE REST-APIs SETZEN AUF CQRS

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

MVC vs. CQRS

23

OKAY. UND WIE IMPLEMENTIERT

MAN DAS JETZT?

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF24

EINFLÜSSE &

GRUNDSÄTZE

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

25

https://37signals.com/manifesto

Google Group DDDinPHP

http://DDDinPHP.org

Gestartet von

Mathias Verraes

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

26

๏ REWORK

๏ Schaffe Overhead ab

๏ Mach es selbst, bis es nicht mehr geht

๏ Entwickle Software für dein Business

๏ Sei konsequent und ehrlich

๏ Mach es so einfach wie möglich

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

27

๏ CLEAN CODE

๏ Namen und Lesbarkeit sind wichtig

๏ Inline-Kommentare sind redundanter Müll

๏ Kohäsion in Klassen

๏ SOLID Prinzipien

๏ Richtig testen & stetiges Refactoring

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

28

๏ GOOGLE GROUP DDD IN PHP

๏ Konvention für Interface-, Class- und Trait-Namen

๏ Domains & Subdomains

๏ Commands & Queries

๏ Aggregates, Entities & Value Objects

๏ Event Sourcing für besseres Verständnis von CQRS

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

29

UNSERE 4 GRUNDSÄTZE

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

30

NO MAGIC$product = Rage::getModel('catalog/product');

# vs.

$product = new Catalog\Product();

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

31

WRITE MORE - DO LESS๏ Spalte Zuständigkeiten in (viele) Klassen auf

๏ Schreibe kurze & aussagekräftige Methoden

๏ Benutze Interfaces, Value-Objects und Type-Hints

๏ Teile keinen Business-Code in mehreren Projekten

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

32

USE (plain) PHP๏ Lerne PHPs Funktionsumfang zu nutzen

๏ Vermeide Drittanbieter-Libraries

๏ Verstehe das Problem - Löse es selbst

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

33

THINK ABOUT THE NEXT DEV๏ Schreibe unmissverständlichen, weisenden Code

๏ Vergebe sprechende (auch lange) Namen

๏ Schreibe (vollständige) Tests

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

EINFLÜSSE & GRUNDSÄTZE

34

NAMENS-KONVENTIONinterface LogsActivity {}

class ActivityLogger {}

trait ActivityLogging {}

class ActivityLogger implements LogsActivity { use ActivityLogging; }

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF35

«Wir brauchen einen Namen!»

«Ja, irgendwas cooles schnelles!»

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF36

ICEHAWK 1.0

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

37

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

38

๏ WAS IST EIN FRAMEWORK?

๏ Session- & Error-Handling initialisieren

๏ URIs auflösen & umschreiben

๏ Lese-Request-Daten weiter reichen

๏ Schreib-Request-Daten weiter reichen

๏ Requests behandeln

๏ Seiten ausliefern & Umleiten

๏ Finale Fehler-Behandlung (für 404 / 500 Seiten)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

39

class IceHawk { public function __construct( $config, $delegate )

public function init() {}

public function handleRequest() {} }

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

40

REQUESTS & RESPONSES

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

41

class RequestInfo {}

class GetRequest {}

abstract class GetRequestHandler {}

class PostRequest {}

abstract class PostRequestHandler {}

REQUEST-VERARBEITUNG

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

42

class Page {}

class NotFound {}

class InternalServerError {}

class Redirect {}

RESPONSES

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

43

DELEGATION & KONFIGURATION

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

44

class IceHawkDelegate { public function setUpSessionHandling() {}

public function setUpErrorHandling() {}

public function handleUncaughtException( \Exception $exception ) {} }

DELEGATION

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

45

class IceHawkConfig { public function getRequestInfo() {}

public function getUriResolver() {}

public function getUriRewriter() {}

public function getDomainNamespace() {} }

KONFIGURATION

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

46

class UriResolver { public function resolveUri(RequestInfo $requestInfo) { # Löse die URI hier auf einen RequestHandler auf

return new UriComponents('Products', 'ShowGallery'); } }

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

47

class UriRewriter { public function rewriteUri(RequestInfo $requestInfo) { # Schreibe die URI hier um (new Redirect('/code/talks/2016'))->respond(); } }

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

48

class SessionRegistry {}

class FormData {}

class Command {}

class Query {}

class IceHawkWasInitializedEvent {}

class HandlingRequestEvent {}

class RequestWasHandledEvent {}

UND…

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

49

RELEASED 30.05.2015

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

50

PAGE 1 PAGE 2

PostRequestHandler MYSQL

BENUTZER EINGABE

COMMAND

QUERYPOST

CLIENT / BROWSER

REDIRECT

GET GET

GetRequestHandler GetRequestHandler

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

51

PAGE 1 PAGE 2

PostRequestHandler MYSQL

BENUTZER EINGABE

COMMAND

QUERYPOST

CLIENT / BROWSER

REDIRECT

GET GET

GetRequestHandler GetRequestHandler

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

52

PAGE 1 PAGE 2

PostRequestHandler MYSQL

BENUTZER EINGABE

COMMAND

QUERYPOST

CLIENT / BROWSER

REDIRECT

GET GET

GetRequestHandler GetRequestHandler

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

53

SCHNELLE AUTOS HABEN ZWEI ENDROHRE

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

54

PAGE 1 PAGE 2

PostRequestHandler MYSQL

BENUTZER EINGABE

COMMAND

QUERYPOST

CLIENT / BROWSER

REDIRECT

GET GET

GetRequestHandler GetRequestHandler

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

55

ETWAS ÜBER 1 JAHR UND…

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

56

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 1.0

57

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF58

PITFALLS

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

59

๏ OPT-IN E-MAILS

๏ RETURN-URLs (z.B. EXTERNE BEZAHLSYSTEM)

๏ AJAX

๏ CSRF TOKENS

๏ UNVOLLSTÄNDIGE READ/WRITE TRENNUNG

๏ UNFLEXIBLES ZUWEISEN VON REQUEST-HANDLERN …WEIL MAGIC

๏ DEFAULT-ROUTING

๏ VERLETZUNG DES SOC-PRINZIPS

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

60

๏ OPT-IN E-MAILS

๏ Kein POST-Request möglich

๏ Option 1: Erneut ein Formular anzeigen

๏ Option 2: Die State-Änderung via GET-Request zulassen + REDIRECT

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

61

๏ RETURN-URLs

๏ Kommen i.d.R. via GET-Request zurück

๏ Lösung: Die State-Änderung via GET-Request zulassen + REDIRECT

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

62

๏ AJAX

๏ Redirects auf GET-Request funktionieren auch nach einem POST-XHR

๏ ALLES GUT

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

63

๏ CSRF-TOKEN

๏ Gehört die Session zum App-State?

๏ Lösung: Nein. Die Session darf auch bei GET-Requests verändert werden.

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

64

๏ UNVOLLSTÄNDIGE READ/WRITE TRENNUNG

๏ Trennung erfolgte erst nach dem Resolving

๏ Events unterschieden nicht nach Read/Write

๏ Finale Fehlerbehandlung unterschied nicht nach Read/Write

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

65

๏ UNFLEXIBLES ZUWEISEN VON REQUEST-HANDLERN …WEIL MAGIC

๏ Suchpfad von Request-Handlern war je Projekt fix

๏ Beim Resolving war nicht ersichtlich, ob auf einen Read oder Write Handler aufgelöst wurde

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

66

๏ DEFAULT-ROUTING

๏ Handler waren oft über 2 URIs erreichbar

๏ Lösung: Default-Routing abschaffen.

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

PITFALLS

67

๏ VERLETZUNG DES SOC-PRINZIPS

๏ Session-Wrapper gehörte nicht ins Framework

๏ FormData gehörte nicht ins Framework

๏ Command / Query gehörten nicht ins Framework

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF68

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF69

REFACTORING

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF70

ICEHAWK 2.0

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 2.0

71

public function getReadRoutes() { return [ new ReadRoute( new Literal('/products/gallery'), new ProductGalleryRequestHandler() ), #... ]; }

NO MAGIC, REALLY

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 2.0

72

class FinalReadResponder { public function handleUncaughtException( \Throwable $throwable, ProvidesReadRequestData $request ); }

FINAL RESPONDING R/W

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 2.0

73

class InitializingIceHawkEvent {}

class IceHawkWasInitializedEvent {}

class HandlingReadRequestEvent {}

class ReadRequestWasHandledEvent {}

class HandlingWriteRequestEvent {}

class WriteRequestWasHandledEvent {}

EVENTS R/W

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 2.0

74

๏ WEITERE "FEATURES"

๏ Unterstützung aller HTTP-Methoden

๏ Interfaces definieren die erlaubten HTTP-Methoden

๏ Auto-Responding auf OPTIONS-Request

๏ "Traitful" Config (Defaults via Traits)

๏ Kein Default-Routing mehr

๏ Literal, RegExp und NamedRegExp URI-Patterns

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

ICEHAWK 2.0

75

๏ NEUE PACKAGES

๏ CSRF-Token Support und Feedback (Forms)

๏ Session Data Mapping (Session)

๏ Messaging (PubSub)

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF76

ICEHAWK FORMS

SESSION PUBSUB

COMING SOON

EVENTSTORE

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF77

BUILD PASSING COVERAGE 100% LICENSE MIT

RC5

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF78

github.com/icehawk

FRAGEN?

phpind.de

VIELEN DANK!

github.com/hollodotme github.com/PHPinDD

@hollodotme / @phpindd

fortuneglobe.com

www.phpug-dresden.org @phpugdd

HOLGER WOLTERSDORF

https://joind.in/talk/f5095

slides available on slideshare

FEEDBACK WELCOME

github.com/icehawk

DIVIDE AND CONQUER • 2 YEARS OF CQRS IN PRODUCTION HOLGER WOLTERSDORF

LINKS / REFERENCES

81

๏ MVC-Pattern: http://martinfowler.com/eaaDev/uiArchs.html ๏ CQRS-Pattern: http://martinfowler.com/bliki/CQRS.html ๏ "Rework" by David Heinemeier Hansson: http://amzn.to/2cWOwxQ ๏ "Clean Code" by Robert C. Martin: http://amzn.to/2dthxQn ๏ Google-Group DDDinPHP: https://groups.google.com/forum/#!forum/dddinphp ๏ "Traitful" Configs: https://phpind.de/posts/traitful-configs

๏ IceHawk Framework on GitHub: https://github.com/icehawk