SubmitOrderCommandHandler - issues

75 views
Skip to first unread message

Paweł Kaczor

unread,
Dec 28, 2011, 9:57:18 AM12/28/11
to ddd-cqr...@googlegroups.com
Hi,
the following questions trouble me after analysing code of SubmitOrderCommandHandler

1) The handler contains business logic:

        Specification<Order> orderSpecification = generateSpecification(systemUser);
        if (! orderSpecification.isSatisfiedBy(order))
            throw new OrderOperationException("Order does not meet specification", order.getEntityId());           

Why this code is not part of Aggregate Root (Order.submit method)?

2) The same handler (SubmitOrderCommandHandler) after invoking submit method on Order AR invokes InvoicingService:

order.submit();       
invoicingService.issuance(order, taxPolicy);

This invocation sequence is also business logic concept and therefore should not be part of CommandHandler. Why submitting Order and invoicing is executed in the same transaction? Those business activities should rather be decoupled and the whole process should be eventually consistent instead of atomicaly. Possibly both activities should be composed into business process (saga). Going further, invoicing might be part of different bounded context than ordering (?).

My assumption is that DDD/CQRS Leaven project should promote architecture and patterns that help handle complex business scenarios and build scalable systems.

Sławomir Sobótka

unread,
Dec 28, 2011, 1:48:28 PM12/28/11
to ddd-cqr...@googlegroups.com
Hi, thanks for questions, because they are a motivation to explain
some decisions.

First of all: this particular handler is just an example of
implementation of certain class of problems.
Other handlers presents approach to other problem classes - they
covers problems You have mentioned.

So let's explain problems and decisions that are behind this particular class:

> Hi,
> the following questions trouble me after analysing code of
> SubmitOrderCommandHandler
>
> 1) The handler contains business logic:
>
>         Specification<Order> orderSpecification =
> generateSpecification(systemUser);
>         if (! orderSpecification.isSatisfiedBy(order))
>             throw new OrderOperationException("Order does not meet
> specification", order.getEntityId());

First we must agree about definition of business vs application logic.
My understanding of the app. logic is: domain orchestration in the
meaning of Use Case/User story modeling. App logic contains also
technical stuff like security and transactions which are Aspect
Advices in this impl.

So this class models the following Use Case:
If Order meets Specification than submit it and issue and Invoice.

We must consider 3 important aspects (not AOP:)
1. "shape" of the Specification tree may depend on not only Business
logic, but also application stuff (logged user, system preferences
etc). So I don't want this concept to be hidden inside domain. I want
to manifest it *explicitly* in Use Case model (app. layer classes)
2. Issuing an Invoice may also depend on application (not domain)
stuff, ex: if system in in PremumMode that automatically issue an
Invoice. Of course this application logic could be implemented in
different way, for example registering or not listeners. But if it
depends on User System Prefernces (user checked "i would like to
generate invoices") that it is problematic.
3. Submitting Order may be one separate Use Case but submitting Order
and issuing Invoice can be another totally separated Use Case. So
let's assume that this class models second Use Case.
And I mean Use Case not just for example checking checbkox on gui and
sending boolean in command:P

> Why this code is not part of Aggregate Root (Order.submit method)?

Actually acceptable could be:
Order.submit(Validator)
there Specification is a validator.

This model would explicitly express that there is a validation
involved in this process.


I don't want to be misunderstood. The best case would be Order.submit
and hiding validation - as You suggest. If case is simple I would
definitely go this way.
But in this particular example We wanted to present something not so
simple and obvious. Considering that Specification creation is
Application (not only Domain) specific we need to go this compromise.


> 2) The same handler (SubmitOrderCommandHandler) after invoking submit method
> on Order AR invokes InvoicingService:
>
> order.submit();
> invoicingService.issuance(order, taxPolicy);
>
> This invocation sequence is also business logic concept and therefore should
> not be part of CommandHandler.

Wrong assumption about level of the logic:P
As explained before. In this example this is not a business but
application (Use Case) logic.
I assume that requirements are not so simple. Sometimes (certain UC)
when submitting Order we need an Invoice, sometimes (another UC) we
don't.

> Why submitting Order and invoicing is
> executed in the same transaction? Those business activities should rather be
> decoupled and the whole process should be eventually consistent instead of
> atomicaly. Possibly both activities should be composed into business process
> (saga). Going further, invoicing might be part of different bounded context
> than ordering (?).

1. Assumption about consistency in this particular example was different.
Let's assume that requirement is "whole process should be consistent".
Let's assume that client says: "If invoicing crashes than rollback
order submission; I demand that and I now what I'm talking about
because I pay".

2. Assumption about BC in this particular example was different.
We can assume that It's all about sales, so one Domain Expert can
grasp it easily.

> My assumption is that DDD/CQRS Leaven project should promote architecture
> and patterns that help handle complex business scenarios and build scalable
> systems.

You are right.

I don't want to be misunderstood.
This particular class presents a very specific Use Case: we must
operate on several Aggregates from the same BC in the consistent way.

All stuff You are writing about (different BCs, Sagas, eventually
consistency) are presented in another places in the code.

We just wanted do go beyond mainstream (mainstream in the CqRS scope;)
buzz and face real problems.
I know that in some domains (trading maybe?) there is at max dozen
aggregate types and millions of events per each instance.
But for example in Hospital Information Systems (kind of ERP for
medical market) there are hundreds of aggregate types and at max dozen
of events per each instance.
But in HIS class systems I want to: 'apply radiation treatment' AND
'apply specific medicine' in consistent way. Doing only one will kill
a human being so nobody cares about "enormous" complexity (2
aggregates in 1 tx;) or scalability (so much).

But as mentioned before: issues You have mentioned may be extremely
important in other contexts, therefore we provided more samples.

Paweł Kaczor

unread,
Dec 29, 2011, 9:48:25 AM12/29/11
to ddd-cqr...@googlegroups.com

First we must agree about definition of business vs application logic.
My understanding of the app. logic is: domain orchestration in the
meaning of Use Case/User story modeling.

In my opinion what you are describing as application logic is in fact description of business process.
 Business processes should be modeled explicitily (as Sagas)

App logic contains also
technical stuff like security and transactions which are Aspect
Advices in this impl.

Right.
But saga could handle special requirements for transactions (if necessary) , I suppose..
 

So this class models the following Use Case:
If Order meets Specification than submit it and issue and Invoice.

We must consider 3 important aspects (not AOP:)
1. "shape" of the Specification tree may depend on not only Business
logic, but also application stuff (logged user, system preferences
etc). So I don't want this concept to be hidden inside domain. I want
to manifest it *explicitly* in Use Case model (app. layer classes)

Logged User is an actor in the process. It is the user that is associated with the business process instance (saga instance).
If business process definition varies depending on system environment (like premium mode) than different process definitions (saga classes) should be deployed on each system.

2. Issuing an Invoice may also depend on application (not domain)
stuff, ex: if system in in PremumMode that automatically issue an
Invoice. Of course this application logic could be implemented in
different way, for example registering or not listeners.

So we will have different process definitions (saga classes). Base process definition could be reused.
 

But if it
depends on User System Prefernces (user checked "i would like to
generate invoices") that it is problematic.

Preferences of the user participating in the process are available during process execution, so I see no problem to build process that
defines some condition (whether to execute some action or not) using those data.

3. Submitting Order may be one separate Use Case but submitting Order
and issuing Invoice can be another totally separated Use Case.

Maybe it is totally separated use case (depending on definition of use case) but it seems to me
that both use cases are part of the same business process.
 

I don't want to be misunderstood. The best case would be Order.submit
and hiding validation - as You suggest. If case is simple I would
definitely go this way.
But in this particular example We wanted to present something not so
simple and obvious. Considering that Specification creation is
Application (not only Domain) specific we need to go this compromise.


I would say that this logic (specification creation and validation) should be placed inside business process (saga). The process is started with
Order creation. Before order enters Submitted state, validation must be performed. Order.submit(specification) makes sense to me.


> Why submitting Order and invoicing is
> executed in the same transaction? Those business activities should rather be
> decoupled and the whole process should be eventually consistent instead of
> atomicaly. Possibly both activities should be composed into business process
> (saga). Going further, invoicing might be part of different bounded context
> than ordering (?).

1. Assumption about consistency in this particular example was different.
Let's assume that requirement is "whole process should be consistent".
Let's assume that client says: "If invoicing crashes than rollback
order submission; I demand that and I now what I'm talking about
because I pay".

If so, we should talk more with the client about what he really wants :)

But in HIS class systems I want to: 'apply radiation treatment' AND
'apply specific medicine' in consistent way. Doing only one will kill
a human being so nobody cares about "enormous" complexity (2
aggregates in 1 tx;) or scalability (so much).

So maybe CQRS is not suitable for those kind of systems :P
 

Sławomir Sobótka

unread,
Dec 29, 2011, 1:35:55 PM12/29/11
to ddd-cqr...@googlegroups.com
Thanks for answers. In general I agree with all.
All Your suggestions are imho correct and useful in many cases (and
most of them are presented in other parts of the code).

I'll remind just to not confuse other readers, that We dare discussing
here specific case.

>> First we must agree about definition of business vs application logic.
>> My understanding of the app. logic is: domain orchestration in the
>> meaning of Use Case/User story modeling.
>
> In my opinion what you are describing as application logic is in fact
> description of business process.
>  Business processes should be modeled explicitily (as Sagas)

Yes, in general we can say that we are dealing with Business Process -
lets define it for purpose of this sample as something that
orchestrates Use Cases.
I agree that BP (same as UC) should be modeled explicitly, somehow.
//If not modeling something that should be modeled we are asking for troubles:)

So how to model BP? We have BP engines, we can do it "by hand" or use
Saga (which is very cool, but people have created tons of software
before even knowing about Sagas, so it should be possible without
using Saga - which is cool).

And indeed there is sample of the long process modeled by saga that
involves payment and shipping.

As mentioned before: submitting Order and issuing an Invoice is just a
sample of the UC (lets say step in BC) that need to be atomic. I guess
that in reap ERP this two activities does not have to be atomic, but
this is just a sample of the technical stuff.
So if invoicing focuses our mind on real world, that lets move to
abstract space: requirement is: Aggregate A and B need to be modified
in consistent way; and someone may ask how to implement this.

>> App logic contains also
>> technical stuff like security and transactions which are Aspect
>> Advices in this impl.
>
> Right.
> But saga could handle special requirements for transactions (if necessary) ,
> I suppose..

hmmm
Saga is event driven. If event is handled asynchronously that
listeners need to call some fixing procedure on the event originator
in case of error.
Could be easier when evens are handler synchronously, but than we
loose scalability (still having decoupling).

The simplest working solution in this case is classic "domain script":
do something with Aggregate A and B.
What could we gain when introducing Sagas? Many sexi things... do we
need them? Depends...

Once again: just a sample of specific class of the problem.

>>
>> So this class models the following Use Case:
>> If Order meets Specification than submit it and issue and Invoice.
>>
>> We must consider 3 important aspects (not AOP:)
>> 1. "shape" of the Specification tree may depend on not only Business
>> logic, but also application stuff (logged user, system preferences
>> etc). So I don't want this concept to be hidden inside domain. I want
>> to manifest it *explicitly* in Use Case model (app. layer classes)
>
> Logged User is an actor in the process. It is the user that is associated
> with the business process instance (saga instance).
> If business process definition varies depending on system environment (like
> premium mode) than different process definitions (saga classes) should be
> deployed on each system.

Ok I agree. In this scenarios needed information about whether issue
an invoice or not can be fetched in Saga or while creating special
Saga.

Problem would be in even simpler case:
User clicks button "submit order" xor "submit order and issue an invoice".
Client tier generates command (command can have boolean switcher or we
can have 2 commands).
Handler submits Order. Order generates event. Where to pass an
information that user wants or not to issue an invoice? Only place is
OrderSubmittedEvent.
So Order.submit need to have parameter that pass this intention. But
we don't want Order to know about Invoice:P

Don't get me wrong. I think Sagas are great and eyes-opening models,
but in this particular sample there is still one requirement:
consistency.

>> I don't want to be misunderstood. The best case would be Order.submit
>> and hiding validation - as You suggest. If case is simple I would
>> definitely go this way.
>> But in this particular example We wanted to present something not so
>> simple and obvious. Considering that Specification creation is
>> Application (not only Domain) specific we need to go this compromise.
>>
>>
> I would say that this logic (specification creation and validation) should
> be placed inside business process (saga). The process is started with
> Order creation. Before order enters Submitted state, validation must be
> performed. Order.submit(specification) makes sense to me.

I'm not sure if I grasp idea, but do You suggest that validation
should be performed in Saga "event listener" method? Therefore in
asynchronous way?
But what if in this special case we need to validate synchronously -
when users performs action, not few minutes later and in case of error
send email (as some rock star conference speakers suggest);P
Just in this particular case sending email "sorry for killing You by
applying radiation treatment and not applying chemical recovery pills"
is not acceptable.

>>
>> > Why submitting Order and invoicing is
>> > executed in the same transaction? Those business activities should
>> > rather be
>> > decoupled and the whole process should be eventually consistent instead
>> > of
>> > atomicaly. Possibly both activities should be composed into business
>> > process
>> > (saga). Going further, invoicing might be part of different bounded
>> > context
>> > than ordering (?).
>>
>> 1. Assumption about consistency in this particular example was different.
>> Let's assume that requirement is "whole process should be consistent".
>> Let's assume that client says: "If invoicing crashes than rollback
>> order submission; I demand that and I now what I'm talking about
>> because I pay".
>
> If so, we should talk more with the client about what he really wants :)

Yea... The Udi's Way:)
I like this way, but engineering is not about liking:P
Ok, I agree that this consideration should be made, this kind of
questions should be asked.
But this sample presents implementation of the case when client claims
he needs consistency.

>> But in HIS class systems I want to: 'apply radiation treatment' AND
>> 'apply specific medicine' in consistent way. Doing only one will kill
>> a human being so nobody cares about "enormous" complexity (2
>> aggregates in 1 tx;) or scalability (so much).
>
> So maybe CQRS is not suitable for those kind of systems :P

Separating responsibility of the code into two parts suits this kind
of systems and imho most of the business systems in general.
But Events, Sagas, Event Sourcing, eventual consistency - cool tools
that solves hard problems (may introduce other) suits some context
more, some contexts less - that's all about this sample handler is.

Paweł Kaczor

unread,
Dec 30, 2011, 12:15:14 PM12/30/11
to ddd-cqr...@googlegroups.com

> I would say that this logic (specification creation and validation) should
> be placed inside business process (saga). The process is started with
> Order creation. Before order enters Submitted state, validation must be
> performed. Order.submit(specification) makes sense to me.

I'm not sure if I grasp idea, but do You suggest that validation
should be performed in Saga "event listener" method? Therefore in
asynchronous way?

Yes, asynchronously because we want to decouple things. But my initial idea to put some logic (specification creation) into Saga was actually wrong (Saga should only send commands, right?). Let me present possible solution (just for fun:), I understand your points about specific requirements that original solution addresses).
OK, so we have to model Order submission and validation and we are allowed to do it asynchronously.
What we need is to enrich Order lifecycle with following states: CREATED, SUBMITTED, REJECTED, APPROVED. Than we can build the following process:
User -> CreateOrderCommand -> Order (status = CREATED) -> OrderCreatedEvent -> OrderSaga started
User -> SubmitOrderCommand -> Order (status = SUBMITTED) -> OrderSubmittedEvent
OrderSaga -> ValidateOrderCommand -> just rough idea (OrderValidationService is called, it creates Specification and invokes Order.validate(specification)) (status = APPROVED or REJECTED) -> Order(Approved|Rejected)Event

Communicating failed validation inside domain (REJECTED/APPROVED state) solves problem with handling exception as discussed here: https://groups.google.com/forum/#!topic/dddcqrs/hDpttk4wNuk/discussion

To be honest, I have no experience with modelling business processes with Sagas. I would like to see some more complex processes designed as Sagas. There are only trivial examples on the web.

Thanks for discussion!

Sławomir Sobótka

unread,
Dec 30, 2011, 5:22:27 PM12/30/11
to ddd-cqr...@googlegroups.com
> Yes, asynchronously because we want to decouple things. But my initial idea
> to put some logic (specification creation) into Saga was actually wrong
> (Saga should only send commands, right?).

This needs clarification...
1. Saga sends commands. Ok. We have API somewhere (set of possible
Commands) and saga can send it. Those commands are API so they can be
potentially sent also by GUI. I think thats ok in general. But
sometimes we would like to reserve some commands to be sent only by
Sagas (but its technical problem of visibility).
But in general is saga need to do sht on the model is should be
encapsulated in app. layer and called via commands.

2. Sega need to decide when to sends commands. For example if certain
events come to Saga, that Saga decides it need to send a command.
So we have some process logic.
More: Saga may send different command depending of events data.


So I don't exactly know what do You mean by "only send commands". Just
a Router that maps events to new commands? If so than it is not
needed. It would be sufficient to install more listeners and skip this
"layer".
What I mean that Saga need to contain some process logic which may be
very heavy business logic - to be able to decide that and hen should
be done.
So If command models Use Case step, than Saga models Business Process
- we agreed about that before. But process definition may require some
logic.

> Let me present possible solution
> (just for fun:), I understand your points about specific requirements that
> original solution addresses).
> OK, so we have to model Order submission and validation and we are allowed
> to do it asynchronously.
> What we need is to enrich Order lifecycle with following states: CREATED,
> SUBMITTED, REJECTED, APPROVED. Than we can build the following process:
> User -> CreateOrderCommand -> Order (status = CREATED) -> OrderCreatedEvent
> -> OrderSaga started
> User -> SubmitOrderCommand -> Order (status = SUBMITTED) ->
> OrderSubmittedEvent
> OrderSaga -> ValidateOrderCommand -> just rough idea (OrderValidationService
> is called, it creates Specification and invokes
> Order.validate(specification)) (status = APPROVED or REJECTED) ->
> Order(Approved|Rejected)Event

That process looks ok, but we must be aware of the very special
approach/style of modeling.
Change of the mindset is to introduce more granular lifecycle:

Actor expressed an intention that he want to submit Order (status = SUBMITTED)
We simply accept that fact, note it in the system and... done:)
This style of modeling is must have if next step is for example long
running activity (needs human action or long computations or
delayed/batch computations)

But I can bet that it would be possible to validate Order immediately
(relatively fast), client would choose synchronous impl and
"smaller"/more automated lifecycle:P
Bout on the other hand, form the architectural point of view: we may
want to build set of "components", "driven" by commands (keep them as
general as possible, so for example validation can be optional) and
than add value by building Sagas on the top of those "components".

> Communicating failed validation inside domain (REJECTED/APPROVED state)
> solves problem with handling exception as discussed here:
> https://groups.google.com/forum/#!topic/dddcqrs/hDpttk4wNuk/discussion
>
> To be honest, I have no experience with modelling business processes with
> Sagas. I would like to see some more complex processes designed as Sagas.
> There are only trivial examples on the web.

Yes, thats the basic problem with all new "toys". We struggle to
understand how and when to use them. On the web there are mostly
"hello world" masturbation samples;)

I think that proper Saga usage can be inspired by Business Process
modeling discipline which (as some claims) can be generalized to
events sending and handling.

> Thanks for discussion!
I would like to thank a lot also. Very productive discussion.

Paweł Kaczor

unread,
Jan 2, 2012, 9:07:22 AM1/2/12
to ddd-cqr...@googlegroups.com
> (Saga should only send commands, right?).

This needs clarification...

You are right...:)
 

What I mean that Saga need to contain some process logic which may be
very heavy business logic - to be able to decide that and hen should
be done.

True. "Process logic" fits better to description of Saga then "Business logic" (but of course process logic is also a business logic).

So I don't exactly know what do You mean by "only send commands". Just
a Router that maps events to new commands? If so than it is not
needed. It would be sufficient to install more listeners and skip this
"layer".

Thanks for pointing this out. Of course, generally You are right but when you read what some well known practitioners say about modeling Sagas things are not so obvious:) This goes into off-topic (and probably deserves another discussion) but let me present what Greg Young said about Sagas (on one of his videos available via torrent):
- Saga should not have decision making capabilities. It is responsible for getting the right information to the right place at the right time so decisions can be made inside of the other places.
- Sagas should not have logic inside of them (business part of the logic). What they have is more like routing logic. What they are doing is they are routing information so the information ends up in the right place at the right time so the right person can make the decision. Choreographing or Orchestrating information instead of 'Command and Control man' in the middle. Much of the logic should not belong to saga but to the other places.
- Ideally we don't want our Saga to have any form of memory. We can move state out of the saga. (one solution Greg presents is to use memento pattern - the saga is informed (woke up) by the scheduler with some concrete event (BillingFailedEvent))


>
> OrderSaga -> ValidateOrderCommand -> just rough idea (OrderValidationService
> is called, it creates Specification and invokes
> Order.validate(specification)) (status = APPROVED or REJECTED) ->
> Order(Approved|Rejected)Event

So, to follow Greg's approach and move decision making out of the Saga the sequence above should be modified :
OrderSaga -> CreateOrderSpecificationCommand -> OrderSpecificationCreatedEvent
OrderSaga -> ValidateOrderCommand -> Order.validate(command.specification) -> OrderApprovedEvent or OrderRejectedEvent

We end up with lot of commands and events traveling on the wire but this is the way to describe our process explicitly. Greg says:
"Commands and Events build the Ubiquitous Language (that describe the process modeled by saga) (integration level domain model)."

This example illustrates also that it is possible to build the process without the state kept in the saga (the state of the process (if required) could be derived from associated domain entity (Order) in this case) (but Udi says it's no longer Saga :) ). But of course I'm not saying that all (or most of) sagas should be stateless. You can use separate listeners to handle this process, but what if you will need to handle timeout scenario? Saga is ready for this.

 
This style of modeling is must have if next step is for example long

running activity (needs human action or long computations or
delayed/batch computations)

or (if building distributed system) you want to be able accept Orders even
is they can not be validated immediately (because validation service is down)

I think that proper Saga usage can be inspired by Business Process

modeling discipline which (as some claims) can be generalized to
events sending and handling.

Yes, I think the missing puzzle is to realize that Sagas can be modeled as state machines, similarly as we model processes using
bpm engines (see: http://processdevelopments.blogspot.com/2007/05/therapy-for-bpm.html)

Example of using state machine with Saga can be found here:  http://blog.jonathanoliver.com/2010/09/cqrs-sagas-with-event-sourcing-part-i-of-ii/
and here: http://blog.jonathanoliver.com/2010/09/cqrs-sagas-with-event-sourcing-part-i-of-ii/

IMHO even this simple saga:
http://code.google.com/p/ddd-cqrs-sample/source/browse/trunk/ddd_cqrs-sample/src/main/java/pl/com/bottega/erp/sales/saga/OrderShipmentStatusTrackerSaga.java
could benefit from applying state machine in the background (I'm thinking of implementing alternative version :) ) Only then you can avoid writing IF statements in the saga code :)

And thanks once more for stimulating me to think more about all of this :)

Sławomir Sobótka

unread,
Jan 2, 2012, 11:50:16 AM1/2/12
to ddd-cqr...@googlegroups.com
>> So I don't exactly know what do You mean by "only send commands". Just
>> a Router that maps events to new commands? If so than it is not
>> needed. It would be sufficient to install more listeners and skip this
>> "layer".
>
> Thanks for pointing this out. Of course, generally You are right but when
> you read what some well known practitioners say about modeling Sagas things
> are not so obvious:) This goes into off-topic (and probably deserves another
> discussion) but let me present what Greg Young said about Sagas (on one of
> his videos available via torrent):
> - Saga should not have decision making capabilities. It is responsible for
> getting the right information to the right place at the right time so
> decisions can be made inside of the other places.

In general I can agree with that.
But because in personal I don't like fascist statements I must ask: "why".

Lets Image that we have 3 "components" driven by commands: A, B, C.
Now I want to "add new value" by building few Sagas above them.
Not one, but few Sagas that differ in details of orchestration
(conditions of the flow).

So I can do it in 2 completely different "styles":

1. Keep components' API as general as possible, therefore I need to
have some logic inside Saga
2. Keep Saga clean, therefore I need to make component's API more
specialized to be able to fulfill

First approach lets You (theoretically;) to add many new Sagas without
touching API.

So if we decide what we want to achieve - or what is possible (is API
modification always possible?) - that we can make architectural
assumptions about responsibility of each Building Block.

> - Sagas should not have logic inside of them (business part of the logic).
> What they have is more like routing logic. What they are doing is they are
> routing information so the information ends up in the right place at the
> right time so the right person can make the decision. Choreographing or
> Orchestrating information instead of 'Command and Control man' in the
> middle. Much of the logic should not belong to saga but to the other places.

OK, that exactly how I understand Saga.
But
how to determine when is the "right time" and what is the "right place"?

Lets assume that in our example the right time to command Warehouse
to send a Package is when all Payments (may be few) plus current
Overpaid is higher than total cost of the Order.
How to model that?
1. We can model some "cashier" component, Saga could send him events,
and cashier could send in proper time an event "AllIsPaid"
Thats possible if we can introduce new components each time we model new Saga.

but...

what is the sens of having such a anemic/routing Saga which just
translates events to commands?
In general what is the purpose of introducing new layer? Introducing
new mental value. But if its just about routing that Events Engine
does the job. If routing in Saga is so simple that each event causes
new Command with no IFs, than proper Listeners would be sufficient and
we don't need to introduce all this sophisticated Sagas machinery.

> - Ideally we don't want our Saga to have any form of memory. We can move
> state out of the saga. (one solution Greg presents is to use memento pattern

Yes, if Saga need to make decision about "when is the proper time"
than it needs state (Memento is very smart way of doing it).

> the state of the process (if required) could be derived from associated domain entity (Order) in this case

nah, I don't like the idea of polluting domain model by process model
- domain should be independent of process, because there may be many
processes that involves the same domain model.
but...
I think now I get Your point... point of all this discussion. At all
makes perfect sense if we assume that process is just a imperative
code, but no sate - process sate is natural property of the domain.
I makes sense as a coherent way of thinking but as mentioned above - I
just don't like it:P


>> This style of modeling is must have if next step is for example long
>>
>> running activity (needs human action or long computations or
>> delayed/batch computations)
>
> or (if building distributed system) you want to be able accept Orders even
> is they can not be validated immediately (because validation service is
> down)

I thing that now we have touched a real context where this
approach/style is simply a killer:)
Distribution is the force that drives design in some way and we are
ready to make come compromises/devotion.

>> I think that proper Saga usage can be inspired by Business Process
>>
>> modeling discipline which (as some claims) can be generalized to
>> events sending and handling.
>
> Yes, I think the missing puzzle is to realize that Sagas can be modeled as
> state machines, similarly as we model processes using
> bpm engines (see:
> http://processdevelopments.blogspot.com/2007/05/therapy-for-bpm.html)
>
> Example of using state machine with Saga can be found here:
> http://blog.jonathanoliver.com/2010/09/cqrs-sagas-with-event-sourcing-part-i-of-ii/
> and here:
> http://blog.jonathanoliver.com/2010/09/cqrs-sagas-with-event-sourcing-part-i-of-ii/
>
> IMHO even this simple saga:
> http://code.google.com/p/ddd-cqrs-sample/source/browse/trunk/ddd_cqrs-sample/src/main/java/pl/com/bottega/erp/sales/saga/OrderShipmentStatusTrackerSaga.java
> could benefit from applying state machine in the background (I'm thinking of
> implementing alternative version :) ) Only then you can avoid writing IF
> statements in the saga code :)
>
> And thanks once more for stimulating me to think more about all of this :)
>

Thanks for Your thought and for links.
Udi's way: http://www.udidahan.com/2009/04/20/saga-persistence-and-event-driven-architectures/
In general we have based our sample on his model.
Only difference is that we have introduced this abject handler that
manipulates 2 Aggregates:)

Reply all
Reply to author
Forward
0 new messages