Loosely
Coupled
Complexity


  Unleash
the
power
of
your
Domain

  Model
using
CQRS
&
Event
Sourcing
       Alberto.brandolini@avanscopertas.it
About
me
In
the
IT
field
since
ZX
Spectrum
Generally
in
large
scale
projects
(I
might
be
biased)
Freelance
consultant:
NotOnlyCode
Trainer
(Freelance
&
Skills
MaKer
+
Zenika)
Technical
Writer
Blogger:
h>p://ziobrando.blogspot.com
TwiKer:
ziobrando


My
e‐mail:

alberto.brandolini@gmail.com
@avanscoperta
www.avanscoperta.it
avanscoperta.wordpress.com
alberto.brandolini@avanscoperta.it




                               ©
Alberto
Brandolini
2009
These
3
guys

have
something

really
interesEng
to

share
What’s
wrong
with
that?



                            ApplicaEon
Services
            Remote
facade
     DTO




                                                  ORM
UI
      DTO




                                                        ©
Alberto
Brandolini
‐
2010
nothing
Thank
you
alberto.brandolini@avanscoperta.it
  hKp://ziobrando.blogspot.com
         twiKer:
ziobrando
...What

hump?




           ‐
Quale
gobba?
How
many
assumpEons

are
driving
our
choices?
let’s
try
again...



                            ApplicaEon
Services
            Remote
facade
     DTO




                                                  ORM
UI
      DTO




                                                        ©
Alberto
Brandolini
‐
2010
Anaemic Domain Model
Anaemic Domain Model

DTOs?
Anaemic Domain Model

DTOs?

Optimizing ORM queries
Anaemic Domain Model

DTOs?

Optimizing ORM queries

Development time
Anaemic Domain Model

DTOs?

Optimizing ORM queries

Development time

Testability
Anaemic Domain Model

DTOs?

Optimizing ORM queries

Development time

Testability

...
Do we really need...
Do we really need...

  a Domain Model?
Do we really need...

  a Domain Model?

  a Database?
Do we really need...

  a Domain Model?

  a Database?

  transactions?
Do we really need...

  a Domain Model?

  a Database?

  transactions?

  an Object Relational Mapper?
Do we really need...

  a Domain Model?

  a Database?

  transactions?

  an Object Relational Mapper?

  DTOs?
Anaemic
Domain
Model

       <<Ser vice>>               <<Entity>>

      OrderService
                                   Order
 registerOrder(...)
                           date
 closeOrder(...)
                           customer
 checkOrder(...)
                           amount
 updateAvailability(...)
                           ...

                           getDate()
                           setDate(...)
                           getCustomer()
                           setCustomer(...)
                           getAmount()
                           setAmount()
                           ...
Not
every
present
is

 necessarily
nice
Advantages
of
Anaemic
Domain
Model
Advantages
of
Anaemic
Domain
Model

1)
Business
code
is
located
in
a
single
place:
Advantages
of
Anaemic
Domain
Model

1)
Business
code
is
located
in
a
single
place:
 Easier
to
read
for
young
developers
not
familiar
with

 OOP
Advantages
of
Anaemic
Domain
Model

1)
Business
code
is
located
in
a
single
place:
 Easier
to
read
for
young
developers
not
familiar
with

 OOP




 Sorry,
can’t
find
number
2
:‐(
Disadvantages
of
Anemic
Domain

            Model




Sad
as
a
hospital
meal
Disadvantages
of
Anemic
Domain

            Model


                 hard
to
maintain




Sad
as
a
hospital
meal
Disadvantages
of
Anemic
Domain

            Model


                 hard
to
maintain
                      hard
to
test



Sad
as
a
hospital
meal
Disadvantages
of
Anemic
Domain

            Model


                  hard
to
maintain
                       hard
to
test
                fosters
duplicaEon


Sad
as
a
hospital
meal
Disadvantages
of
Anemic
Domain

            Model


                  hard
to
maintain
                       hard
to
test
                fosters
duplicaEon


Sad
as
a
hospital
meal
How
to
shoot
yourself
in
the
foot




                          avanscoper
                              ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model




                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering




                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering
  Pretend that you’re doing TDD and start testing your domain classes




                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering
  Pretend that you’re doing TDD and start testing your domain classes
      Particularly getters and setters




                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering
  Pretend that you’re doing TDD and start testing your domain classes
      Particularly getters and setters

  Now start testing the logic with Integration Tests and get stuck by
  test data related issues




                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering
  Pretend that you’re doing TDD and start testing your domain classes
      Particularly getters and setters

  Now start testing the logic with Integration Tests and get stuck by
  test data related issues
  Declare that TDD provides no benefit and only slows you down




                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering
  Pretend that you’re doing TDD and start testing your domain classes
      Particularly getters and setters

  Now start testing the logic with Integration Tests and get stuck by
  test data related issues
  Declare that TDD provides no benefit and only slows you down
  Comment tests in your Build-Integration process


                                                         avanscoper
                                                             ta
How
to
shoot
yourself
in
the
foot
  Design your application starting from the data model
  Create your domain model by reverse engineering
  Pretend that you’re doing TDD and start testing your domain classes
      Particularly getters and setters

  Now start testing the logic with Integration Tests and get stuck by
  test data related issues
  Declare that TDD provides no benefit and only slows you down
  Comment tests in your Build-Integration process
  Keep on whining
                                                         avanscoper
                                                             ta
I won’t reverse engineer my
data model to create a
domain model
I won’t reverse engineer my
data model to create a
domain model

I won’t reverse engineer my
data model to create a
domain model
I won’t reverse engineer my data
model to create a domain model

I won’t reverse engineer my data
model to create a domain model

I won’t reverse engineer my data
model to create a domain model
I won’t reverse engineer my data
model to create a domain model

I won’t reverse engineer my data
model to create a domain model

I won’t reverse engineer my data
model to create a domain model

I won’t reverse engineer my data
model to create a domain model
I won’t reverse engineer my data model to
create a domain model

I won’t reverse engineer my data model to
create a domain model

I won’t reverse engineer my data model to
create a domain model

I won’t reverse engineer my data model to
create a domain model

I won’t reverse engineer my data model to
create a domain model
I won’t reverse engineer my data model to create a
domain model

I won’t reverse engineer my data model to create a
domain model

I won’t reverse engineer my data model to create a
domain model

I won’t reverse engineer my data model to create a
domain model

I won’t reverse engineer my data model to create a
domain model

I won’t reverse engineer my data model to create a
domain model
How
should
we
implement
a
Domain
Model?
How
should
we
implement
a
Domain
Model?
How
should
we
implement
a
Domain
Model?
Behavior
should
be

placed
in
the


Domain
Model
How
should
we
implement
a
Domain
Model?
Behavior
should
be

placed
in
the


Domain
Model
Have
your
code

speak
the
Ubiquitous

Language
How
should
we
implement
a
Domain
Model?
Behavior
should
be

placed
in
the


Domain
Model
Have
your
code

speak
the
Ubiquitous

Language
Use
Aggregates
as
unit

of
consistency
across

your
domain
model
How
should
we
implement
a
Domain
Model?
Behavior
should
be

placed
in
the


Domain
Model
Have
your
code

speak
the
Ubiquitous

Language
Use
Aggregates
as
unit

of
consistency
across

your
domain
model
Protect
your
model

with
clearly
defined

Bounded
Contexts
Anemic
Domain
Model

      <<Ser vice>>               <<Entity>>

     OrderService
                                  Order
registerOrder(...)
                          date
closeOrder(...)
                          customer
checkOrder(...)
                          amount
updateAvailability(...)
                          ...

                          getDate()
                          setDate(...)
                          getCustomer()
                          setCustomer(...)
                          getAmount()
                          setAmount()
                          ...
Rich
domain
model          <<Value Object>>
                          <<Entity>>
           ....
                                     Order           LineItem
registerOrder(...)
                          date               goods
closeOrder(...)
                          customer           quantity
checkOrder(...)
                          amount             notes
updateAvailability(...)
                          ...
                                             calculate amount()
                          update()           ...
                          close()
                          ship()
                          ...


                                             <<Value Object>>
                          <<Value Object>>
                                                      Money
                                  Customer
                                             currency
                          name               amount
                          surname
                          address            plus(Money other)
                                             minus(Money other)
                          annota()...        ...
s
           TDD
and
DDD
                       Frequent
rewriEng

       Focus
on
Unit
Tests
                               Exploratory
coding
    Frequent
Short
Cycles
                             Tiny
Domain
Objects
               Quick
Feedback
                    Self
explanatory
code
                         Freedom
to
change   ©
Alberto
Brandolini
‐
2010
Aggregate




            ©
Alberto
Brandolini
‐
2010
Aggregate


A
group
of
objects
that

naturally
belong
together
Unit
of
consistency
in
the

domain
model

updated
in
the
same

transacEon
deleted
together
transferred
together

                              ©
Alberto
Brandolini
‐
2010
Aggregate
                              <<Entity>>         <<Value Object>>

                                         Order           LineItem
                              date               goods
A
group
of
objects
that
      customer
                              amount
                                                 quantity
                                                 notes

naturally
belong
together
                              ...
                                                 subtotal()
                              update()           ...
                              close()
Unit
of
consistency
in
the
   ship()
                              ...

domain
model                  <<Value Object>>
                                                 <<Value Object>>

                                                            Money
                                      Customer
                                                 currency

updated
in
the
same

                              name               amount
                              surname
                              address            plus(Money other)

transacEon
                                                 minus(Money other)
                                                 ...


deleted
together
transferred
together

                                                         ©
Alberto
Brandolini
‐
2010
MulEple
aggregates
                               Money
                    currency
                    amount

                    plus(Money other)
                    minus(Money other)
                    ...




 <<Entity>>         <<Root>>             <<Value Object>>
                                                                                     <<Entity>>    <<Root>>
            Order                                    LineItem
                                                                                             Customer
 date                                    goods
                                                                                     name
 customer                                quantity
                                                                                     surname
 amount                                  notes
                                                                                     address
 ...
                                         subtotal()                                  ...
 update()                                ...
                                                                                     updateDiscount()
 close()
                                                                                     ...
 ship()
 ...


                                              shipping address
 <<Value Object>>

      CustomerData
                                   billing address
 name
 surname                                                         <<Value Object>>

                                                                           Address
                                              <<Value Object>>   street
                                                                 city
                                                                 country
                                                                 zipcode




                                                                                                              ©
Alberto
Brandolini
‐
2010
Isn’t
duplicaEon
bad?
‐   If
you
think
“data”
then,
...there’s
duplica6on

‐   If
you
think
“behaviour”
then
some
objects

    definitely
are
not
the
same


‐   enforcing
aggregates
boundaries
makes
your
system
    ‐   strictly
consistent
within
the
aggregate
boundaries

    ‐   eventually
consistent
outside
the
aggregate
boundaries




                                                         ©
Alberto
Brandolini
‐
2010
It
turns
out
to
be
simple




                            ©
Alberto
Brandolini
‐
2010
Why
does
it
have
to
be
hard?




                          ©
Alberto
Brandolini
‐
2010
Hmm...
Once
coupling

between

aggregates
is

dramaEcally

reduced,
I
can

potenEally
choose

a
different

persistence

strategy
for
each

aggregate...
                     ©
Alberto
Brandolini
‐
2010
From
the
same
old
stuff



                            ApplicaEon
Services
            Remote
facade
     DTO




                                                  ORM
UI
      DTO




                                                        ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view



                             ApplicaEon
Services
             Remote
facade
      DTO




                                                   ORM
UI
       DTO




                                                         ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view
           bou
             c o n n de d
                  te x
                       ts




                             ApplicaEon
Services
             Remote
facade
      DTO




                                                   ORM
UI
       DTO




                                                         ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view



                             ApplicaEon
Services
             Remote
facade
      DTO




                                                   ORM
UI
       DTO




                                                         ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view
            ag g
                 r   bou           ega
                               n d a te
                                    r ie
                                         s




                             ApplicaEon
Services
             Remote
facade
      DTO




                                                   ORM
UI
       DTO




                                                         ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view



                             ApplicaEon
Services
             Remote
facade
      DTO




                                                   ORM
UI
       DTO




                                                         ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view
     t hi
            na
                pp l


                                          ApplicaEon
Services
                          Remote
facade
             l ay ic at io
            DTOe r         n




                                                                ORM
UI
              DTO




                                                                      ©
Alberto
Brandolini
‐
2010
TradiEonal
DDD
view



                             ApplicaEon
Services
             Remote
facade
      DTO




                                                   ORM
UI
       DTO




                                                         ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?




                            ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?

‐ Nobody
really
likes
DTOs...




                                ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?

‐ Nobody
really
likes
DTOs...
‐ Some
tools
allow
that!
(let’s
have
some
more

  hawaiian
shirts)




                                         ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?

‐ Nobody
really
likes
DTOs...
‐ Some
tools
allow
that!
(let’s
have
some
more

  hawaiian
shirts)
‐ Validafon
creep


                                         ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?

‐ Nobody
really
likes
DTOs...
‐ Some
tools
allow
that!
(let’s
have
some
more

  hawaiian
shirts)
‐ Validafon
creep
‐ Double
state
objects

                                         ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?

‐ Nobody
really
likes
DTOs...
‐ Some
tools
allow
that!
(let’s
have
some
more

  hawaiian
shirts)
‐ Validafon
creep
‐ Double
state
objects
 ‐   Framework
temptafon
:‐(


                                         ©
Alberto
Brandolini
‐
2010
Sending
Domain
Objects
to
the
UI?

‐ Nobody
really
likes
DTOs...
‐ Some
tools
allow
that!
(let’s
have
some
more

                                           ens
  hawaiian
shirts)
                                         ap p
                                   at  h is
‐ Validafon
creep              W h         I
                                          U rom
                                    t he t f
‐ Double
state
objects          in
                                       er en in
 ‐   Framework
temptafon
:‐(     d iff oma
                                      e d
                                   th        l!
                                       o de
                                    m   ©
Alberto
Brandolini
‐
2010
How
would
you
implement
this?
                         As a Sales Office
                         I want to ship order on purchase
                         command
                         In order to deliver purchased
                         goods to the customer
As a Marketing Office
I want to assign discount points
to customer on every purchase
In order to enable more deals in
the future


                                                ©
Alberto
Brandolini
‐
2010
Events
and
aggregate
coordinaEon
 ‐ Operafons
spanning
mulfple

    aggregates
shouldn’t
be
in
the
same

    Unit
of
Work


‐   Communicafon
between
aggregates
       <<Domain Event>>
    is
inherently
asynchronous                   OrderPurchased


‐   Domain
Events
as
a
communicafon

                                           order
                                           where
    mechanism                              when
                                           amount
    ‐   from
the
outside                   payment method

    ‐   among
aggregates                   ...

                                           ...

                                                       ©
Alberto
Brandolini
‐
2010
Domain
Event


‐ in
the
Ubiquitous
Language,
they’re

 Completed
AcEons:
verbs
in
past
tense.




                                   ©
Alberto
Brandolini
‐
2010
Asynchronously
responding
to
events
                                                          <<Domain Event>>
                                                                OrderPurchased

                                                          order
                                                          where
                                                          when
                                                          amount
      <<Entity>>       <<Root>>                           payment method         s u bs                    <<Entity>>    <<Root>>
                                                   s to   ...                             cri b
               Order              su b   s c ri be                                                e s to
                                                                                                                   Customer
      date                                                ...
                                                                                                           name
      customer
                                                                                                           surname
      amount
                                                                                                           address
      ...
                                                                                                           ...
      onPurchaseEvent(...)
                                                                                                           onPurchaseEvent(...)
      update()
                                                                                                           updateDiscount()
      close()
                                                                                                           ...
      ship()
      ...




‐   Don’t
forget:
Business
rules
everything!!!

                                                                                                                        ©
Alberto
Brandolini
‐
2010
SOA
Anyone?
...just
draw
it
differently

     and
think
about

   “service
granularity”
Command/Query

 Responsibility

  SegregaEon
Why
do
we
have
to

choose
a
trade‐off?
StarEng
small...

‐ Command/Query
SeparaEon
was
an
OOD

 principle
part
of
DDD
 ‐   accessors
shouldn’t
have
side
effects
 ‐   mutators
shouldn’t
return
a
value

     ‐   (with
the
excepfon
of
this
in
some
cases)




                                                     ©
Alberto
Brandolini
‐
2010
Command



!
      Usually
targeted
to
single
enEEes
      Behaviour
maKers
      Flexibility
maKers




                                ©
Alberto
Brandolini
‐
2010
Query



?
        Large
amount
of
data
        No
behavior
        Performance
maKers
        Availability
of
off‐the
shelves
components
                                         ©
Alberto
Brandolini
‐
2010
!
?
         UI
              DTO



   DTO
Remote
facade
ApplicaEon
Services
                      from
this...




         ORM
!
?
                     UI
               DTO
                          DTO
                                           ...to
this


Remote
facade             Remote
facade
                          ApplicaEon
Services




 Thin
Read
Layer




                                ORM
!
        A
separate
path
for

      commands
issued
to
the

          Domain
Model




?   A
separate
path
for
querying

                Data
?               Querying
‐   Have
a
look
to
Users,
what
are

    they
really
interested
in?
    ‐   It’s
not
searching,
it’s
finding
    ‐   It’s
not
refreshing,
it’s

        looking
for
events
                                  ©
Alberto
Brandolini
‐
2010
?               Staleness
‐ Is
it
really
so
bad?
‐ Does
it
really
maKers
if
the
data
is...

    ‐ 20
seconds
old?
    ‐ Or
10
minutes?
‐ ...
who
are
we
to
decide
this?
‐ ...
can
you
keep
a
print
in
sync?
                                      ©
Alberto
Brandolini
‐
2010
?            It’s
just
data


‐   There’s
no
behaviour
in
what
we
see.
‐ Do
we
really
need
objects
for
that?

                                  ©
Alberto
Brandolini
‐
2010
?       Query‐Only
Architecture
‐   It’s
just
(stale)
data:
no
behaviour...
    ‐   =>
Why
don’t
we
go
straight
to
the
database?

‐   No
coupling
between
UI
screens...
    ‐   =>
Do
we
really
need
referenEal
integrity?

    ‐   =>
Why
don’t
we
just
a
table‐per‐UI‐view
strategy,

        calculated
in
the
background?

‐   What
are
we
already
doing
with
the
search
model

    and
the
cache?
                                                         ©
Alberto
Brandolini
‐
2010
?        Even
stale
data
can


‐ ...
provide
useful
informafon
for

    preliminary
validaEon
of
commands
    ‐ =>
less
failing
commands

                                       ©
Alberto
Brandolini
‐
2010
!      ...less
failing
commands
    ‐ Since
most
of
our
commands
will
actually

      pass...
    ‐ ...
do
we
really
need
to
answer
immediately

      on
the
same
channel?
    ‐ What
about:
“Thank
you
for
your
order,
your

      confirmaDon
e‐mail
will
arrive
shortly”?


                                            ©
Alberto
Brandolini
‐
2010
!             Capturing
user
intent
    ‐   Do
we
really
know
what
the
user
wants
to
do
with

        our
applicaEon?

    ‐   Are
we
really
suppor6ng
our
users?

    ‐   Who’s
carrying
the
complexity
burden?

    ‐   ...
can’t
we
do
anything
smarter
than
just
showing

        raw
data?
        ‐   ...most
of
the
load
olen
turns
out
to
be
simply
useless


                                                             ©
Alberto
Brandolini
‐
2010
!          Commands
!=
EnEEes


    ‐   There’s
not
so
much
in
common




                                        ©
Alberto
Brandolini
‐
2010
!                 Write‐only
model
    ‐   The
domain
model
is
not
used
to
collect
or
to
display

        data
        ‐   Query
oriented
relafonships
between
enffes
no
longer

            needed.

    ‐   The
Domain
Model
is
always
in
a
consistent
state
(from

        Factory
to
Garbage
Collecfon)

    ‐   No
validaEon
on
the
Domain
Model
(commands
are

        validated
before)

    ‐   Tesfng
the
Domain
Model
turns
even
simpler

                                                             ©
Alberto
Brandolini
‐
2010
!              PersisEng
the
model


    ‐   Do
we
really
need
to
persist
all
the
data?

    ‐   Do
we
really
need
to
persist
it
in
Relafonal
Form?
        ‐   (remember,
we’re
not
running
queries...)




                                                       ©
Alberto
Brandolini
‐
2010
!
?
                     UI
               DTO
                          Commands


Remote
facade             Remote
facade
                          ApplicaEon
Services




 Thin
Read
Layer




                                     ORM
!
?
                      UI
                                                            voilà



               DTO
                                           Commands


Remote
facade                              Remote
facade
                                           ApplicaEon
Services




 Thin
Read
Layer




                                                       ORM?

                     Eventually
                       publish
subscribe
voilà

!

                                                                              ORM?
                                    ApplicaEon
Services
                    Remote
facade
         Commands




                                                                                     Eventually
    UI                                                    Sp e publish
subscribe
                                                              cia
                                                                  l i ze
                                                              mo d d a
                    Remote
facade
            DTO




?
                                                                   de l  ta



                                                            Thin
Read
Layer
!
?
                      UI
                                                            voilà



               DTO
                                           Commands


Remote
facade                              Remote
facade
                                           ApplicaEon
Services




 Thin
Read
Layer




                                                       ORM?

                     Eventually
                       publish
subscribe
do e
    voilà                                                       s it




!
                                                          t o b re
                                                                e re a l l y




                                                                                   ORM?
                                    ApplicaEon
Services
                    Remote
facade
                                                                     l at ne e
                                                                         io n      d
                                                                              a l?


         Commands




                                                                                          Eventually
    UI              Remote
facade                                           publish
subscribe
            DTO




?                                                                Thin
Read
Layer
!
?
                      UI
                                                            voilà



               DTO
                                           Commands


Remote
facade                              Remote
facade
                                           ApplicaEon
Services




 Thin
Read
Layer




                                                       ORM?

                     Eventually
                       publish
subscribe
!               A
nice
side
effect
    ‐   ...
fewer
collecfons

    ‐   =>
less
memory
footprint

    ‐   =>
less
Garbage
Collecfon

    ‐   on
some
systems,
the
DM
is
basically
always

        available




                                                   ©
Alberto
Brandolini
‐
2010
The
paper‐based
system



Many
business
pre‐date
computers
TransacEons
are
ocen
NOT
a

business
concern
Data
might
be
stale...
accept
it
ASK
the
Business
Event
Sourcing
!       So
what
is
our
DM
doing?

    ‐   basically
answering
to
self
contained
external

        messages...
        ‐   events
from
the
UI
or
from
external
sources




                                                          ©
Alberto
Brandolini
‐
2010
!   Single
source
of
truth?




                        ©
Alberto
Brandolini
‐
2010
!        Single
source
of
truth?


    ‐   Once
it
used
be
paper...





                                    ©
Alberto
Brandolini
‐
2010
!      Single
source
of
truth?


    ‐Once
it
used
be
paper...

    ‐ now
the
best
candidate
is
Events



                                 ©
Alberto
Brandolini
‐
2010
!
?
                     UI
                                                          voilà

                                         Events




               DTO
Remote
facade                            Remote
facade
                                         ApplicaEon
Services




 Thin
Read
Layer




                                                      ORM
?

                     Events
                     publish
subscribe
!       Do
we
need
state
in
EnEEes?

    ‐   We
have
all
the
needed
informafon
in
the
Event

        Queue
        ‐   SINGLE
SOURCE
of
TRUTH

    ‐   What’s
an
Aggregate?
something
that
changes
its

        state
according
to
events
        ‐   ...according
to
the
current
understanding
of
the
system




                                                            ©
Alberto
Brandolini
‐
2010
!      Aggregates
and
events
                                           OrderCreated
                                                              MAY

                                                                 3
                                                              MAY
                                             ItemsAdded

                             Order
                                                                 5
    Aggregates
   date
                  customer                 PriceUpdated
                                                              MAY

                                                               10
    track

                  amount
                  ...


    Events
and

                  onItemsAdded(...)                           MAY
                                          Order Purchased
                  onPriceUpdated(...)
                  onOrderPurchased(...)                        12
    derive
       ...
                                                              MAY
                                           Order Shipped

    state
from
                                                15
    that                                   OrderDelivered
                                                              MAY

                                                               25
                                                              JUN
                                          PaymentReceived
                                                               26

                                                       ©
Alberto
Brandolini
‐
2010
!                 What
if
we...
    ‐ derive
the
Aggregate
state
from
the
sequence
of

      events
that
occurred
in
the
system?

    ‐ =>
We
can
add
retroacEve
features...
    ‐ =>
We
can
say
YES
to
a
lot
of
interesfng/awkward

      request
for
the
business.

    ‐ =>
Reproducing
bugs?

                                               ©
Alberto
Brandolini
‐
2010
!



    ©
Alberto
Brandolini
‐
2010
The
land
of
opportunity
Loosely
coupled

aggregates
allow
            be>er

simpler
                     scalability
development

Polyglot

persistence
       Painless
        Rewindable

       SOA              applicaEons
Start
small
you
might
not
need
all
of
it
       each
step
is
an

        improvement
 Even
in
Eny
architectures
      ...challenge
one

   assumpEon
at
a
Eme
References

   h>p://groups.google.com/group/dddcqrs

h>p://cqrs.wordpress.com/

h>p://www.infoq.com/interviews/Architecture‐Eric‐Evans‐Interviews‐Greg‐Young

h>p://www.udidahan.com/2009/12/09/clarified‐cqrs/

h>p://www.infoq.com/presentaEons/Command‐Query‐Responsibility‐SegregaEon

h>p://www.infoq.com/presentaEons/SOA‐Business‐Autonomous‐Components

h>p://marEnfowler.com/eaaDev/EventSourcing.html

h>p://skillsma>er.com/podcast/design‐architecture/architectural‐innovaEon‐evenEng‐
event‐sourcing


                                                                      ©
Alberto
Brandolini
‐
2010
Thank
you
alberto.brandolini@avanscoperta.it
  hKp://ziobrando.blogspot.com
         twiKer:
ziobrando

Loosely Coupled Complexity - Unleash the power of your Domain Model with Command Query Responsibility Segregation and Event Sourcing

Editor's Notes

  • #4 And that&amp;#x2019;s the company I started one year ago.
  • #5 Disclaimer: this is second-hand talk. 99% of the ideas come from these three guys. In the last couple of years a little revolution has being going on in the DDD community: Udi Dahan (left) and Greg Young (right) have brought new ideas in the DDD landscape.
  • #6 Ok, let&apos;s start from a familiar architecture, what&apos;s wrong with that?
  • #8 Ok, if that&amp;#x2019;s the answer... If you really like that and think that&amp;#x2019;s the best possible world... then I don&amp;#x2019;t have so much to tell you.
  • #9 On the other hand, if you really think about it, there are a few things in your familiar architecture that you&amp;#x2019;ve been probably too used to. Enough to forget that there might be a different way.
  • #10 Let&amp;#x2019;s try again, with a clear mind.
  • #12 Here are some of the things we might not like.
  • #13 Here are some of the things we might not like.
  • #14 Here are some of the things we might not like.
  • #15 Here are some of the things we might not like.
  • #16 Here are some of the things we might not like.
  • #17 Here are some of the things we might not like.
  • #18 And here are some of the questions we might ask ourselves
  • #19 And here are some of the questions we might ask ourselves
  • #20 And here are some of the questions we might ask ourselves
  • #21 And here are some of the questions we might ask ourselves
  • #22 And here are some of the questions we might ask ourselves
  • #23 And here are some of the questions we might ask ourselves
  • #24 Ok, let&amp;#x2019;s start from the anaemic domain model: in the picture red is where the logic is. As you might see, there&amp;#x2019;s not so mouch in the Order class...
  • #25 How did we get there? Well sometimes it&amp;#x2019;s just a matter of features that came for free, like a tool that allows you to reverse engineering your database to create domain classes.
  • #26 Ok, but anaemic domain model is probably the dominant pattern throughout the world, so it must have some advantages: let&amp;#x2019;s dig into them.
  • #27 Ok, but anaemic domain model is probably the dominant pattern throughout the world, so it must have some advantages: let&amp;#x2019;s dig into them.
  • #28 Ok, but anaemic domain model is probably the dominant pattern throughout the world, so it must have some advantages: let&amp;#x2019;s dig into them.
  • #29 Let&amp;#x2019;s look at the drawbacks instead... in two words it provides all the architetural complexity of an OOP system with the advantages in maintenance of a procedural one. :-P
  • #30 Let&amp;#x2019;s look at the drawbacks instead... in two words it provides all the architetural complexity of an OOP system with the advantages in maintenance of a procedural one. :-P
  • #31 Let&amp;#x2019;s look at the drawbacks instead... in two words it provides all the architetural complexity of an OOP system with the advantages in maintenance of a procedural one. :-P
  • #32 Let&amp;#x2019;s look at the drawbacks instead... in two words it provides all the architetural complexity of an OOP system with the advantages in maintenance of a procedural one. :-P
  • #33 So what should we do instead?
  • #34 So what should we do instead?
  • #35 So what should we do instead?
  • #36 So what should we do instead?
  • #37 So what should we do instead?
  • #38 So what should we do instead?
  • #39 So what should we do instead?
  • #40 So what should we do instead?
  • #41 I think this is a really sensible resolution :-)
  • #46 ... you got the point ;-) Let&amp;#x2019;s try to be a little more constructive
  • #47 For example, Mr. Eric Evans has something really interesting to say about how should we implement a Domain Model:
  • #48 For example, Mr. Eric Evans has something really interesting to say about how should we implement a Domain Model:
  • #49 For example, Mr. Eric Evans has something really interesting to say about how should we implement a Domain Model:
  • #50 For example, Mr. Eric Evans has something really interesting to say about how should we implement a Domain Model:
  • #51 For example, Mr. Eric Evans has something really interesting to say about how should we implement a Domain Model:
  • #52 What does it mean to &amp;#x201C;put behaviour in the domain model&amp;#x201D;? Here is our starting point: all the logic is in the service class.
  • #53 In a &amp;#x201C;Rich&amp;#x201D; Domain Model (I really don&amp;#x2019;t know why is Rich vs Anaemic, maybe &amp;#x201C;bloody domain model&amp;#x201D; or &amp;#x201C;poor domain model&amp;#x201D; weren&amp;#x2019;t ok for the job) le logic is &amp;#x201C;where it belongs&amp;#x201D; according to Single Responsibility Principle (Martin) or Information Expert (Larman). It&amp;#x2019;s not spread equally... Customer doesn&amp;#x2019;t do much, while Money for example looks like a pure data type, but has a lot of math-related behaviour in it.
  • #54 Interestingly, TDD and DDD form a perfect match: DDD needs TDD for many of the key practices, while TDD naturally enforces DDD-like coding styles. It&amp;#x2019;s just perfect.
  • #55 The next key DDD building block is Aggregates. The Domain Model isn&amp;#x2019;t flat. Some links are stronger than others (and UML doesn&amp;#x2019;t really help much in rendering it). If we start considering consistency and behaviour as the primary drivers for modeling our domain we&amp;#x2019;ll end up with something quite different from a 1-1 projection of the data model.
  • #56 The next key DDD building block is Aggregates. The Domain Model isn&amp;#x2019;t flat. Some links are stronger than others (and UML doesn&amp;#x2019;t really help much in rendering it). If we start considering consistency and behaviour as the primary drivers for modeling our domain we&amp;#x2019;ll end up with something quite different from a 1-1 projection of the data model.
  • #57 For example, in this case we&amp;#x2019;ll notice some duplication, related to customer. But lifecycles of the customer and of the order are different. If a customer moves, we don&amp;#x2019;t want to have all of our past orders changed, at the same time if an order needs to be canceled, we don&amp;#x2019;t want the user to get down the sink as well. A little duplication is what allows aggregate lifecycles to be independent.
  • #58 Some data-driven analyst are probably really good in spotting these problems just out of their experience.
  • #59 But really, this part of modeling is our everyday work, and should be easy as walking back home in a sunny day.
  • #60 Shouldn&amp;#x2019;t really have to rely on the experience of some rarely available guy that knows all the traps and hidden perils of data modeling.
  • #61 But here&amp;#x2019;s something to think about: this modeling style enforces loose coupling between aggregates. As a side effect, queries tend to be a lot simpler and focused. In many situations, this opens the door for some alternative persistence strategy.
  • #62 Ok, so let&amp;#x2019;s see how DDD can improve our application architecture.
  • #63 Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don&amp;#x2019;t change that much. ... is there anything else that we can do?
  • #64 Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don&amp;#x2019;t change that much. ... is there anything else that we can do?
  • #65 Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don&amp;#x2019;t change that much. ... is there anything else that we can do?
  • #66 Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don&amp;#x2019;t change that much. ... is there anything else that we can do?
  • #67 Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don&amp;#x2019;t change that much. ... is there anything else that we can do?
  • #68 Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don&amp;#x2019;t change that much. ... is there anything else that we can do?
  • #69 Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
  • #70 Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
  • #71 Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
  • #72 Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
  • #73 Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
  • #74 Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
  • #75 Ok, question for the audience: two Stories, hitting different portions of the application, triggered by the same external event. How would you model them? I must admit that in a similar situation I spent some time wondering: &amp;#x201C;Is it better to have order.purchase(customer, ...) or customer.purchase(order, ...)?&amp;#x201D; or many other variation on the theme.
  • #77 That&amp;#x2019;s the very specific Greg Young&amp;#x2019;s definition. I like it.
  • #78 Domain Events as a communication means between aggregates really simplify things a lot, even at the conceptual level. - Do they really belong to the same transaction? - Would you want the order to roll-bak if you are unable to process the discount for the next order bu the same customer? ... but really, how the two things should be related, is a business choice! We just have more and more possibilites in our arsenal.
  • #79 There&amp;#x2019;s been a never ending debate in the SOA community (and many dollars and euros wasted) about &amp;#x201C;service granularity&amp;#x201D;. A good read of the blue book could have helped a lot, the solution was already there...
  • #80 Let&amp;#x2019;s start to bite something bigger
  • #81 Which one is the right shoe for you? Well ...it depends :-) each one serves a particular use. We change shoes according to what we want to do.
  • #82 So why should we have only one architecture?
  • #83 CQS existed before DDD and was part of the DDD toolkit collection, basically at the class design level. It really enhances scalability and maintainability.
  • #84 But CQRS promotes the same concept at the architectural level. Commands and quesries have different needs.
  • #85 When we ask, there is generally no behavior involved. Just data.
  • #86 So one first step might be to evolve the &amp;#x201C;classical&amp;#x201D; DDD architecture...
  • #87 ... into something more specialized: the domain model is used only in the command side, while the query side is definitely thinner.
  • #89 Let&amp;#x2019;s dive into the query side. Udi Dahan pointed out that sometimes the biggest source of optimization is to have a look at what the users are really doing: capturing user intent might surprise you.
  • #90 Also, the fact that we can sometimes provide real time data, doesn&amp;#x2019;t really mean that we must alway provide them. Most of the time a little of delay is absolutely acceptable. Sometimes requirements are not even coming from the business, it&amp;#x2019;s just IT people showing off...
  • #91 Wow, that is a kind of shock for DDD zealots. Objects are there for the behavior. The domain model is an efficient way to represent behavior. If there&amp;#x2019;s no behavior then there&amp;#x2019;s no real need for objects as well. Did I mention that we could get rid of some of our assumptions? ;-)
  • #92 How would you optimize a Query Only architecture? - we could just use some of the tools vendor provide us to manage straight data. - we could have a specialized model for the view, with different table structure, eventually updated by a background process. - ... and many other cool ideas!
  • #93 Also, even stale data could be a great help in managing pleliminary validation of the commands. We can still perform validation on the presentation layer and make sure that most of the commands simply won&amp;#x2019;t fail.
  • #94 Let&amp;#x2019;s see the consequences on the command side. More trust means less burden, and a little less synchronicity, meaning less load.
  • #95 Commands are a lot closer to user intent. It&amp;#x2019;s not just editing data. Is ding it with a purpose.
  • #96 ... so why should show entities in the presentation layer?
  • #97 The domain model turns out to become even simpler: it&amp;#x2019;s write only. Classes are always in a consistent state and a command issued to the class, triggers an action and/or a state transition. Just that.
  • #98 Let&amp;#x2019;s get back to the gorilla... what do we need to persist? and How? What&amp;#x2019;s the most efficient strategy for persisting a domain model?
  • #99 Let&amp;#x2019;s shake things a little bit more :-)
  • #100 The next little revolution is to have 2 different persistence storage: one optimized fopr working with the domain model? the other one optimized for the Query Only model. The two are eventually consistent. Just think about how many locking issues are blown away by separating the two...
  • #101 The next little revolution is to have 2 different persistence storage: one optimized fopr working with the domain model? the other one optimized for the Query Only model. The two are eventually consistent. Just think about how many locking issues are blown away by separating the two...
  • #102 The next little revolution is to have 2 different persistence storage: one optimized fopr working with the domain model? the other one optimized for the Query Only model. The two are eventually consistent. Just think about how many locking issues are blown away by separating the two...
  • #103 The next little revolution is to have 2 different persistence storage: one optimized fopr working with the domain model? the other one optimized for the Query Only model. The two are eventually consistent. Just think about how many locking issues are blown away by separating the two...
  • #104 Objects are tiny now. No collections, no mapping. Intersting things might happen...
  • #105 Surprisingly, but Udi Dahan and Greg Young in their speeches at last DDDx put the paper-based system at the center of their concern. If a complex system could work without computers ...there must be a reason for that. Some times computers just loeded the systems with more unnecessary complexity.
  • #106 Let&amp;#x2019;s now face another assumption...
  • #107 You might also want to have a look to Alistair Cockburn exagonal architecture, you might find quite a few similarities in the problem setting.
  • #108 There might be inconsistencies in the data or between the data and the paper. In many system (especially those data-entry based) the paper used to be the Single Source of Truth, but larger integrated systems Events are probably a better candidate.
  • #109 There might be inconsistencies in the data or between the data and the paper. In many system (especially those data-entry based) the paper used to be the Single Source of Truth, but larger integrated systems Events are probably a better candidate.
  • #110 So Events are passing from the command side to the Query side in a publish-subscribe fashion, they need to ba made persistent as well
  • #111 In such a model, what&amp;#x2019;s the best way to model an entity? Our aggregates are receiveng entities and updating state, can we achieve the same result with a more efficient strategy?
  • #112 The Specification pattern turns out really useful for that, but also note that entities are a little less mutable than they used to be.
  • #113 This might be a blast! Think about the amount of opportunities
  • #114 Ok, this one is a picture I really like, and reuse over and over... DDD has a lot to do with learning. But Event sourcing is a learning tool as well! Only, stop assuming that Business People know everything about the business, there&amp;#x2019;s a lot more to learn for them also! Why not doing it together?
  • #115 Surprisingly, googling &amp;#x201C;land of opportunity&amp;#x201D; leads to Arkansas. But I like this picture... :-)
  • #116 One important lesson: you don&amp;#x2019;t need all of this at once. But every little step brings an improvement, and it&amp;#x2019;s worth taking.
  • #117 despite how cool this stuff looks ...be pragmatic.
  • #118 Ok, time for some useful link