prooph/event-sourcing

Change event handling methods

prolic opened this issue · 8 comments

Currenty we use something like this:

protected function apply(AggregateChanged $e)
{
    $handler = $this->determineEventHandlerMethodFor($e);

    if (! method_exists($this, $handler)) {
        throw new \RuntimeException(sprintf(
            'Missing event handler method %s for aggregate root %s',
            $handler,
            get_class($this)
        ));
    }

    $this->{$handler}($e);
}

New approach with be like this:

protected function apply(AggregateChanged $event) {
    switch (get_class($event)) {
    case ManagerWasBlocked::class:
        $this->whenManagerWasBlocked($event); // delegate to when...-method
        break;
    case ManagerWasDeleted::class:
        $this->state = ManagerState::DELETED(); // handle immediately
        break;
    default:
        throw new \UnexpectedValueException('Unknown domain event');
    }
}

Reasons:

  • performance
  • possibilty to call when-event-name-methods within is still possible
  • use of custom event names (f.e. using dots) is easy

refers to: prooph/service-bus#109

oqq commented

This issue depends on an open PR, which benchmarks the apply method. I will provide more cases, especially for a switch construct. #32

I would like to decide if a event is handled by an "on" method in the aggregate. With the current implementation i have to create always an empty 'when' method, if not. With your approach that would be possible. So +1

@oqq Please note this: In the event sourcing lib, there are less problems, as we always expect the event to be an instance of AggregateChanged. But in the service-bus a message (command, event or query) doesn't have to be an object. It can also be an array or string. So here an onEvent-method helps really a lot to handle those situations for listeners.

oqq commented

Ok, so i write benchmarks for event sourcing with the assume it would be an instance of AggregateChanged. I have started to test against strings. Thanks for the hint. :)

Looks good. Migrating existing code to this is also easy. You have to write a little bit more code, but the flexibility/performance is worth it.

@oqq You find some extended bench examples here.

oqq commented

We could provide some examples in docs, so the user could catch from templates for the implementation. Maybe with a reference to benchmarks.

Prefer this method, looks more functional too.

👍 for the approach
you could also use the old approach as fallback in the default case so users don't need to migrate all their aggregates at once and prooph-cli would continue to work if you use it.

Fallback is already available in this repo:

protected function apply(AggregateChanged $e): void

it's protected an can simply be overridden in userland code to achive the "new style".