Customizing aggregate behaviour

Hi,

I have question about how to implement custom aggregate lifecycle. My scenarion looks like this:

  • I have library where is PlayerAggregate which represents a player which can play some game for example
  • In another project I want to use that PlayerAggregate, but I want to add/change some its behaviour.
  • I know that player can be in states PLAYING, DEAD
  • depends on what state player is, I want to react on events from PlayerAggregate which are
    about to apply. For example, lets say that there is command MovePlayer(…) (which is in the same library as
    PlayerAggregate) and before event PlayerMoved is applied I want to react on that: if player is in state DEAD I throw
    exception like PlayerCannotMoveWhenDead.
  • I also want to listen for evens which happened in that aggregate and change player state and maybe generate other
    domain events

I hope you get a point what I want to do. I have some library with predefined aggregates, commands and events. I’m going
to used that library in my own applications and I want to customize aggregates behaviour.

I have two ideas how ti implement this:

  1. I can create class Lifecycle extends AbstractAnnotatedEntity, so it will
    be basically part of aggregate.
  • I can send command like CreatePlayer(…, MyCustomPlayerLifecycle.class) and new instance is created in
    PlayerAggregate constructor.

pros

  • I can listen for domain events by @EventHandler and make state transitions
  • Before I create and apply events I can pass it to the lifecycle to check them if they are valid in
    current state

cons

  • how can I call methods on PlayerAggregate? I cannot simply call apply(new SomeEvent()) without aggregate
    validation. I can get reference on PlayerAggregate and call its methods but there is another problem
    that if I call two methods which are dependend, it does not work because event are queued and applied after
    end of unit of work.
  1. Another way is to implement lifecycle as a Saga. When PlayerAggregate with some lifecycle is created, new instance
    of Saga is created for that aggregate which will manage its lifecycle.

pros

  • I can listen for domain events by @EventHandler and make state transitions

cons

  • If I want to make some actions on PlayerAggregate from the saga lifecycle, I can simply send commands,
    but I want to make sure that all commands are successfull or all are rollbacked, so I have same problem as in 1)
  • When PlayerAggregate want to change its state it must send an request event, saga can accept or reject that,
    depends on its current state and then send commands to PlayerAggregate. I don’t like this communication.

I want to know if anyone has experience with this scenario and how should I solve that. It will be cool to have some predefined aggregates, with
an API (events, commands and exceptions) with possibility to change/add some custom behaviour instead of creating new aggregate of subclassing.

Hi Adam,

You problem does sound a bit vague, but I’ll fire some ideas at you to see if any one sticks.
Using entities or subclasses for customizing behavior is common pattern. It’s basically what OO is about ;-).
Also consider the possibility to use the strategy pattern. You can have clients (component sending a command) define which behavior for specific areas they wish to use. You could use them to provide specific behavior of your characters/players. An Undead, for example can still move when dead ;-).

Hope some of this sticks.
Cheers,

Allard