Aggregate transition - Explicit state modeling

132 views
Skip to first unread message

Zeljko Vujaklija

unread,
Apr 15, 2016, 10:00:43 AM4/15/16
to DDD/CQRS
I'm trying to model aggregate transition from state to state with transition in both directions i.e.State1 --> State2 and State2 --> State1.

I'm also trying to model transitions using explicit states inspired by Greg Young's article http://codebetter.com/gregyoung/2010/03/09/state-pattern-misuse/ and this one https://medium.com/@martinezdelariva/explicit-state-modeling-f6e534c33508#.oma4xgpa6.

For example, there is SalesOrderRequest AR that can transition to WarehouseFulfillment AR. In other words, sales department is making a Order Request and than it's forwarded to other department (warehouse) for fulfillment.
For whatever reason warehouse department can ask for Order Request changes. In that case WarehouseFulfillment should transition back to SalesOrderRequest.

I should mention I'm using event sourcing.

public class SalesOrderRequest
{
  private Guid _id:
  private bool _isActive = true;

  public SalesOrderRequest(Guid id)
  {
    this.Update(new SalesOrderRequestMadeEvent(id));
  }

  public WarehouseFulfillment ForwardToWarehouse()
  {
    this.Update(new ForwardedToWarehouseEvent());
    return WarehouseFulfillment.CreateNew(_id);
  }

  public void Reopen()
  {
    this.Update(new SalesRequestReopenedEvent() );
  }

  private void OnForwardedToWarehouse(ForwardedToWarehouseEvent e)
  {
    _isActive = false;
  }

  private void OnSalesOrderRequestMade(SalesOrderRequestMadeEvent e)
  {
    _id = e.Id;
   _isActive = true;
  }

  private void OnReopened(SalesRequestReopenedEvent e)
  {
    _isActive = true;
  }
}

public class WarehouseFulfillment 
{
  private Guid _id:
  private bool _isActive = true;
  
  public SalesOrderRequest SendBackToSales()
  {
    this.Update(new SentBackToSalesEvent() );
    return new SalesOrderRequest.CreateNew(_id);
  }
  
  private OnSentBackToSales(SentBackToSalesEvent e)
  {
    _isActive = false;
  }
}

What I'm struggling with is how to model WarehouseFulfillment. 
Specifically, should SendBackToSales return new  SalesOrderRequest ? In that case SalesOrderRequestMadeEvent will be appended to SalesOrderRequest and _isActive will be set to true. 
But that event is not "true". SalesOrderRequest is reopened not made.

Is there another way ?

Also, domain service that handles transition back to SalesOrderRequest looks like this

public class OrderTransitionService : IOrderTransitionService
{
  public void SendRequestBackToSales(Guid requestId)
  {
    WarehouseFulfillment fulfillment = _warehaouseFulfillmentRepo.GetById(requestId);
    SalesOrderRequest  salesOrderRequest = fulfillment.SendBackToSales();
    
    salesOrderRequestRepo.Add(salesOrderRequest);

    _unitOfWork.Commit();
  }
}

Since I'm using unit of work (both repositories share the same instance of uow) changes on both aggregates are persisted in the same transaction.

But, I'm altering two aggregates in same transaction which I think is a no no.

Maybe I should also mention both aggregates have its own event stream. By own event stream I mean events are loaded (filtered) by aggregate id and aggregate type. So, although both AR have same id, they differ by type.



Kijana Woodard

unread,
Apr 15, 2016, 10:33:25 AM4/15/16
to ddd...@googlegroups.com
I ordered some books from Amazon the other day.
After a day or so, I realized I wanted a different format [larger paperback].

I couldn't "change" the format, I had to cancel the old format and order the new ones.
When I went to cancel, the item got a note that said ~"Attempting to cancel item".

It turns out I was too late and they shipped them.
It wasn't already shipped when I tried to cancel.

The cost to return them [shipping] is ~50% of the price I paid for the book [free outbound shipping with Prime].
I just kept them to give as gifts.

Not everything has to change atomically.
People understand if you communicate clearly.



--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Zeljko Vujaklija

unread,
Apr 15, 2016, 3:14:32 PM4/15/16
to DDD/CQRS
If I understood your answer correctly, you are saying that state transition doesn't have to be atomical (in one transaction).
In other words, I can model transitions using process (saga).

In that case saga would handle ForwardedToWarehouseEvent and SentBackToSalesEvent and call appropriate methods on ARs.
For example, command handler would call WarehouseFulfillment.SendBackToSales method while saga would handle SentBackToSalesEvent  and call for example SalesOrderRequest.Reopen method - 2 transactions.

@yreynhout

unread,
Apr 20, 2016, 1:03:03 PM4/20/16
to DDD/CQRS
"For whatever reason" ... there's something worth exploring.
Reply all
Reply to author
Forward
0 new messages