CQRS – Eine Einführung
Pt. 2 – Event-Centric Architecture
                                      .Net Online Usergroup – 20.02.2011

                                                  Presenter: Dennis Traub

                   Speaker, Trainer, Author, Software Developer since 1991

                                                        Twitter: @DTraub
CQRS Revisited

Domain Events

An Event-Centric Architecture

Some Code

What about Testing?

Summary
CQRS revisited

                     Data Storage


               ORM                 Thin Read Layer

         Domain Model

       Command Handlers


    Commands                                Queries

                          Client
CQRS Revisited

Domain Events

An Event-Centric Architecture

Some Code

What about Testing?

Summary
Definition: Domain Event
• Martin Fowler: (PEAA, 2002)
 ▫ Captures the memory of something interesting
   which affects the domain

 ▫ The essence […] is to capture things that can
   trigger a change to the state

 ▫ These event objects are then processed to cause
   changes to the system, and stored to provide an
   audit log
State


        Shopping Cart
What we dont know:
What led to this state?
Added
  to
 Cart
Added   Added
  to      to
 Cart    Cart
Added   Added   Added
  to      to      to
 Cart    Cart    Cart
Added   Added   Added   Removed
  to      to      to      from
 Cart    Cart    Cart     Cart
Which model contains
 more Information?
This one?


            Shopping Cart
Or this one?




 Added    Added   Added   Removed
   to       to      to      from
  Cart     Cart    Cart     Cart
What if we capture every single event?
And reproduce state from
 this stream of events?
An Event Stream …


Added   Added   Added   Removed
  to      to      to      from
 Cart    Cart    Cart     Cart
An Event Stream …


Added      Added          Added   Removed
  to         to             to      from
 Cart       Cart           Cart     Cart




                                            Shopping
                                              Cart
 Can be projected into:
An Event Stream …


Added          Added      Added   Removed
  to             to         to      from
 Cart           Cart       Cart     Cart




                                            Sales History
                                                     Shopping
                                                        Cart
        … or into this:
An Event Stream …


Added          Added      Added   Removed
  to             to         to      from
 Cart           Cart       Cart     Cart




                                            Sales History
                                              Audit Trail
                                                     Shopping
                                                        Cart
        … or into this:
An Event Stream …


Added          Added      Added   Removed
  to             to         to      from
 Cart           Cart       Cart     Cart




                                       Sales History
                                    Campaign Effectiveness
                                                Shopping
                                     Campaign Effectiveness
                                                   Cart
        … or into this:
CQRS Revisited

Domain Events

Towards an Event-Centric Architecture

Some Code

What about Testing?

Summary
Simple CQRS
     Relational Data                 SQL
         Storage                    Views


           ORM                  Thin Read Layer

     Domain Model

   Command Handlers


Commands                                 Queries

                       Client
Optimized Write / Complex to Read
                       INNER JOIN …
                       LEFT OUTER JOIN …
     Relational Data   UNION …                  SQL
         Storage       GROUP BY …              Views


           ORM                             Thin Read Layer

     Domain Model

   Command Handlers


Commands                                            Queries

                         Client
Optimized Write / Complex to Read
                       INNER JOIN …
                       LEFT OUTER JOIN …
     Relational Data   UNION …                  SQL
         Storage       GROUP BY …              Views


           ORM                             Thin Read Layer

     Domain Model

   Command Handlers


Commands                                            Queries

                         Client
Replace Views with Table per Query
                                SELECT * FROM …


                                                  Table
     Relational Data                               per
         Storage                                  Query



           ORM                             Thin Read Layer

     Domain Model

   Command Handlers


Commands                                                  Queries

                       Client
Emit Events when they occur
                                     Table
     Relational Data                  per
         Storage                     View



           ORM                  Thin Read Layer

     Domain Model

   Command Handlers


Commands                                     Queries

                       Client
Denormalize Events into Read Model




                                Denormalizer
                                                    Table
     Relational Data                                 per
         Storage                                    View



           ORM                                 Thin Read Layer

     Domain Model

   Command Handlers


Commands                                                    Queries

                       Client
Add an Event Log for future retrieval




                                Denormalizer
                                                    Table
     Relational Data                                 per
         Storage                                    View



           ORM                                 Thin Read Layer

     Domain Model

   Command Handlers


Commands                Event Log                           Queries

                       Client
Simplified:

                   Events

          Domain             Read Model



   Commands                         DTOs



                    Client
CQRS Revisited

Domain Events

Towards an Event-Centric Architecture

Some Code

What about Testing?

Summary
Denormalized Store:
If ISBN exists in ShoppingCartDetails
    Increase Amount
Else
    Add New Row
Denormalized Store:
If Shopping Cart ID exists in ShoppingCartSummary
    Increase Number of Items
    Add Offered Price to Total Amount
Else
    Add New Row
Denormalized Store:
If Amount > 1 in ShoppingCartDetails
    Decrease Amount
Else
    Delete Row
Denormalized Store:
Subtract Offered Price from Total Amount
Decrease Number of Items
CQRS Revisited

Domain Events

Towards an Event-Centric Architecture

Some Code

What about Testing?

Summary
Testing the Read Model




                  Denormalizer
                                      Table
                                       per
                                      View



                                 Thin Read Layer
Testing the Read Model
Given that certain Events have occurred




                                          Denormalizer
                                                              Table
                                                               per
                                                              View



                                                         Thin Read Layer
Testing the Read Model
Given that certain Events have occurred




                                          Denormalizer
                                                              Table
                                                               per
When a specific Event has occurred                            View



                                                         Thin Read Layer
Testing the Read Model
Given that certain Events have occurred




                                          Denormalizer
                                                              Table
                                                               per
When a specific Event has occurred                            View



                                                         Thin Read Layer




Then each query should produce the expected results
Testing the Read Model

Given that a book with an ISBN of xxx and a
      price of USD 24.00 was added to a new shopping cart

When   a book with an ISBN of yyy and a price
       of USD 19.00 was added to that same shopping cart

Then   the Shopping Cart Summary should contain 2 books
       and have a total amount of USD 43.00

And    the Shopping Cart Details should contain book xxx

And    the Shopping Cart Details should contain book yyy
Testing the Write Model



    Domain Model

  Command Handlers
Testing the Write Model



                     Given that certain Events have occurred
    Domain Model

  Command Handlers
Testing the Write Model



                      Given that certain Events have occurred
     Domain Model

   Command Handlers

                           When a specific Commands is sent
Commands
Testing the Write Model
             Then the expected Events (and only those) should be emitted




                                 Given that certain Events have occurred
     Domain Model

   Command Handlers

                                      When a specific Commands is sent
Commands
Testing the Write Model

Given that an Add Book To Shopping Cart event with
      an ISBN of xxx had been sent

When   a Remove Book From Shopping Cart command is
       sent with an ISBN of zzz

Then   a Book Removal Failed event should be emitted

And    NO Book Was Removed From Shopping Cart event
       should be emitted
CQRS Revisited

Domain Events

Towards an Event-Centric Architecture

Some Code

What about Testing?

Summary
Main Value:
• Additive only, i.e. we don‘t lose information

• Linearly scalable and distributable Read Model

• Every new view can be created from the
  beginning of time

• We can come up with new questions at any time

• Built-In Integration Model
Proven Technology:
Mature business models move away from
Update/Delete and become purely transactional:

 ▫   Human Resources   ▫ Banking
 ▫   Medicine          ▫ Financial Trading
 ▫   Bookkeeping       ▫ Government
 ▫   …
What we haven‘t touched yet:


 ▫ Messaging        ▫ Eventual Consistency
 ▫ Event Sourcing   ▫ Integration Scenarios
 ▫ Sagas            ▫…
Resources
• http:// cqrs.wordpress.com

• http:// groups.google.com/group/dddcqrs

• http:// distributedpodcast.com

• http:// abdullin.com/cqrs

• http://cqrs.wikidot.com
Vielen Dank!
     Dennis Traub
          @Dtraub

  Please rate this talk at:
    bit.ly/xyb4tx

CQRS-Einführung - Teil 2

  • 1.
    CQRS – EineEinführung Pt. 2 – Event-Centric Architecture .Net Online Usergroup – 20.02.2011 Presenter: Dennis Traub Speaker, Trainer, Author, Software Developer since 1991 Twitter: @DTraub
  • 2.
    CQRS Revisited Domain Events AnEvent-Centric Architecture Some Code What about Testing? Summary
  • 3.
    CQRS revisited Data Storage ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 4.
    CQRS Revisited Domain Events AnEvent-Centric Architecture Some Code What about Testing? Summary
  • 5.
    Definition: Domain Event •Martin Fowler: (PEAA, 2002) ▫ Captures the memory of something interesting which affects the domain ▫ The essence […] is to capture things that can trigger a change to the state ▫ These event objects are then processed to cause changes to the system, and stored to provide an audit log
  • 6.
    State Shopping Cart
  • 7.
    What we dontknow: What led to this state?
  • 8.
  • 9.
    Added Added to to Cart Cart
  • 10.
    Added Added Added to to to Cart Cart Cart
  • 11.
    Added Added Added Removed to to to from Cart Cart Cart Cart
  • 12.
    Which model contains more Information?
  • 13.
    This one? Shopping Cart
  • 14.
    Or this one? Added Added Added Removed to to to from Cart Cart Cart Cart
  • 15.
    What if wecapture every single event?
  • 16.
    And reproduce statefrom this stream of events?
  • 17.
    An Event Stream… Added Added Added Removed to to to from Cart Cart Cart Cart
  • 18.
    An Event Stream… Added Added Added Removed to to to from Cart Cart Cart Cart Shopping Cart Can be projected into:
  • 19.
    An Event Stream… Added Added Added Removed to to to from Cart Cart Cart Cart Sales History Shopping Cart … or into this:
  • 20.
    An Event Stream… Added Added Added Removed to to to from Cart Cart Cart Cart Sales History Audit Trail Shopping Cart … or into this:
  • 21.
    An Event Stream… Added Added Added Removed to to to from Cart Cart Cart Cart Sales History Campaign Effectiveness Shopping Campaign Effectiveness Cart … or into this:
  • 22.
    CQRS Revisited Domain Events Towardsan Event-Centric Architecture Some Code What about Testing? Summary
  • 23.
    Simple CQRS Relational Data SQL Storage Views ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 24.
    Optimized Write /Complex to Read INNER JOIN … LEFT OUTER JOIN … Relational Data UNION … SQL Storage GROUP BY … Views ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 25.
    Optimized Write /Complex to Read INNER JOIN … LEFT OUTER JOIN … Relational Data UNION … SQL Storage GROUP BY … Views ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 26.
    Replace Views withTable per Query SELECT * FROM … Table Relational Data per Storage Query ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 27.
    Emit Events whenthey occur Table Relational Data per Storage View ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 28.
    Denormalize Events intoRead Model Denormalizer Table Relational Data per Storage View ORM Thin Read Layer Domain Model Command Handlers Commands Queries Client
  • 29.
    Add an EventLog for future retrieval Denormalizer Table Relational Data per Storage View ORM Thin Read Layer Domain Model Command Handlers Commands Event Log Queries Client
  • 30.
    Simplified: Events Domain Read Model Commands DTOs Client
  • 31.
    CQRS Revisited Domain Events Towardsan Event-Centric Architecture Some Code What about Testing? Summary
  • 35.
    Denormalized Store: If ISBNexists in ShoppingCartDetails Increase Amount Else Add New Row
  • 36.
    Denormalized Store: If ShoppingCart ID exists in ShoppingCartSummary Increase Number of Items Add Offered Price to Total Amount Else Add New Row
  • 38.
    Denormalized Store: If Amount> 1 in ShoppingCartDetails Decrease Amount Else Delete Row
  • 39.
    Denormalized Store: Subtract OfferedPrice from Total Amount Decrease Number of Items
  • 40.
    CQRS Revisited Domain Events Towardsan Event-Centric Architecture Some Code What about Testing? Summary
  • 41.
    Testing the ReadModel Denormalizer Table per View Thin Read Layer
  • 42.
    Testing the ReadModel Given that certain Events have occurred Denormalizer Table per View Thin Read Layer
  • 43.
    Testing the ReadModel Given that certain Events have occurred Denormalizer Table per When a specific Event has occurred View Thin Read Layer
  • 44.
    Testing the ReadModel Given that certain Events have occurred Denormalizer Table per When a specific Event has occurred View Thin Read Layer Then each query should produce the expected results
  • 45.
    Testing the ReadModel Given that a book with an ISBN of xxx and a price of USD 24.00 was added to a new shopping cart When a book with an ISBN of yyy and a price of USD 19.00 was added to that same shopping cart Then the Shopping Cart Summary should contain 2 books and have a total amount of USD 43.00 And the Shopping Cart Details should contain book xxx And the Shopping Cart Details should contain book yyy
  • 46.
    Testing the WriteModel Domain Model Command Handlers
  • 47.
    Testing the WriteModel Given that certain Events have occurred Domain Model Command Handlers
  • 48.
    Testing the WriteModel Given that certain Events have occurred Domain Model Command Handlers When a specific Commands is sent Commands
  • 49.
    Testing the WriteModel Then the expected Events (and only those) should be emitted Given that certain Events have occurred Domain Model Command Handlers When a specific Commands is sent Commands
  • 50.
    Testing the WriteModel Given that an Add Book To Shopping Cart event with an ISBN of xxx had been sent When a Remove Book From Shopping Cart command is sent with an ISBN of zzz Then a Book Removal Failed event should be emitted And NO Book Was Removed From Shopping Cart event should be emitted
  • 51.
    CQRS Revisited Domain Events Towardsan Event-Centric Architecture Some Code What about Testing? Summary
  • 52.
    Main Value: • Additiveonly, i.e. we don‘t lose information • Linearly scalable and distributable Read Model • Every new view can be created from the beginning of time • We can come up with new questions at any time • Built-In Integration Model
  • 53.
    Proven Technology: Mature businessmodels move away from Update/Delete and become purely transactional: ▫ Human Resources ▫ Banking ▫ Medicine ▫ Financial Trading ▫ Bookkeeping ▫ Government ▫ …
  • 54.
    What we haven‘ttouched yet: ▫ Messaging ▫ Eventual Consistency ▫ Event Sourcing ▫ Integration Scenarios ▫ Sagas ▫…
  • 55.
    Resources • http:// cqrs.wordpress.com •http:// groups.google.com/group/dddcqrs • http:// distributedpodcast.com • http:// abdullin.com/cqrs • http://cqrs.wikidot.com
  • 56.
    Vielen Dank! Dennis Traub @Dtraub Please rate this talk at: bit.ly/xyb4tx

Editor's Notes

  • #4 Refactor Application Service Call to Object => CommandCommands can
  • #7 Refactor Application Service Call to Object => CommandCommands can
  • #8 Refactor Application Service Call to Object => CommandCommands can
  • #9 Refactor Application Service Call to Object => CommandCommands can
  • #10 Refactor Application Service Call to Object => CommandCommands can
  • #11 Refactor Application Service Call to Object => CommandCommands can
  • #12 Refactor Application Service Call to Object => CommandCommands can
  • #13 Refactor Application Service Call to Object => CommandCommands can
  • #14 Refactor Application Service Call to Object => CommandCommands can
  • #15 Refactor Application Service Call to Object => CommandCommands can
  • #16 Refactor Application Service Call to Object => CommandCommands can
  • #17 Refactor Application Service Call to Object => CommandCommands can
  • #18 Refactor Application Service Call to Object => CommandCommands can
  • #19 Refactor Application Service Call to Object => CommandCommands can
  • #20 Refactor Application Service Call to Object => CommandCommands can
  • #21 Refactor Application Service Call to Object => CommandCommands can
  • #22 Refactor Application Service Call to Object => CommandCommands can
  • #24 Refactor Application Service Call to Object => CommandCommands can
  • #25 Refactor Application Service Call to Object => CommandCommands can
  • #26 Refactor Application Service Call to Object => CommandCommands can
  • #27 Refactor Application Service Call to Object => CommandCommands can
  • #28 Refactor Application Service Call to Object => CommandCommands can
  • #29 Refactor Application Service Call to Object => CommandCommands can
  • #30 Refactor Application Service Call to Object => CommandCommands can
  • #31 Refactor Application Service Call to Object => CommandCommands can
  • #42 Refactor Application Service Call to Object => CommandCommands can
  • #43 Refactor Application Service Call to Object => CommandCommands can
  • #44 Refactor Application Service Call to Object => CommandCommands can
  • #45 Refactor Application Service Call to Object => CommandCommands can
  • #46 Refactor Application Service Call to Object => CommandCommands can
  • #47 Refactor Application Service Call to Object => CommandCommands can
  • #48 Refactor Application Service Call to Object => CommandCommands can
  • #49 Refactor Application Service Call to Object => CommandCommands can
  • #50 Refactor Application Service Call to Object => CommandCommands can
  • #51 Refactor Application Service Call to Object => CommandCommands can