My entity is too fat and deep! - Unavoidable constraint the Aggregate Root?


(Joo) #1

Hello guys,

I treat my persistent entity as an aggregate root, and I try to stick to this definition as much as possible and often find myself designing the entity that is quite fat.

I will give you an example.

In our system, our customers can have multiple investment “goals”, and the investment goals are supported by following the investment “plans”. And each investment plans have one portfolio, and the portfolio consist of multiple financial instruments.

When one of the plan’s instruments position got updated because the trade has settled, we have to renew the market value of

  1. customer’s overall combined market values and combined instrument positions
  2. market value of the goal that is supported by this plan
  3. plan’s market value.
  4. portfolio’s instrument position

For us, 1,2,3 and 4 must be renewed atomically at the same time, otherwise, we will confuse our clients and we cannot take that risk.

And this is a strong signal to me that Goal / Plan / Position objects all need to be in the same aggregate root.

It means that your entity’s state will be something like this:

case class GoalManagerState(manager:GoalManager)

And this state consists of nested objects:

case class GoalManager(goalId:UUID, goals:List[Goal])

case class Goal(plans:List[Plan])

case class Plan(instrumentPositions:List[InstrumentPosition])

case class InstrumentPosition(currentPosition:BigDecimal, settledOrders:List[Order])

case class Order(.......)

As you can see, this results in an entity that is very deep with many layers of nested objects inside of it. It will make the command handling and event handling very complex.

I’ve been dealing with such kind of complexities by using the traits, but still, I am wondering if this is a common thing with aggregate root. I am wondering how other Lagom users are dealing with this kind of complexities.

Thanks,

Joo


(Alan Klikic) #2

Hi,

If i understand correctly, you have a consistency problem with each view being mutually consistent.
Your requirement is to have consistent aggregated view when position is updated.

If you split all in each aggregate root/microservice, each generated view is eventual consistent but not mutually consistent.
My opinion is that you solution for solving mutual consistancy problem by modeling one big aggregate root/microservice is is an anti-pattern. Your are basically building micro-monoliths.
Check Sizing individual microservices.

You could model this in the way to split all in each aggregate root/microservice and implement separate service responsible for update saga process and generating the aggregated view. So aggregated view is updated when saga process is done and information is mutually consistent.

I hope this helps.

Br,
Alan


(Joo) #3

Thanks a lot Alan. I had the same feeling too. How would you build your saga process in such cases? Can you share some guidelines?

Thanks again


(Alan Klikic) #4

Hi,

I will have a saga pattern showcase demo project available for community soon (maybe next week).

Br,
Alan


(Joo) #5

Thanks Alan. Looking forward for it.