What do you think about introducing some standards regarding CQRS and Event 
sourcing? 

I have a working/in production web based CRM application that uses one of 
my micro-frameworks <https://github.com/xprt64/cqrs-es> . It uses the 
command handler style described on cqrs.nu, where command handlers are 
aggregate methods. The aggregate is identified by the ID (extracted from 
Command) and class (manually/automatically subscribed). 

The normal flow is this (the flow implemented by my DefaultCommandDispatcher
):
- the client code (i.e. a REST endpoint) creates a new Command and it sends 
the command to the CommandDispatcher
- the CommandDispatcher identifies the aggregate class (using 
CommandSubscriber)  and ID (using Command::getAggregateId) then creates a 
new aggregate instance
- it rehydrates the aggregate from the event store (by loading all the 
prior events and applying them to the aggregate instance)
- it calls the aggregate's command method (identified by using 
CommandSubscriber) and collects the yielded events (also it applies them 
onto the aggregate itself, one by one, at collect time - a kind of reactive 
aggregate); 
- it persists the collected events to the EventStore, FutureEventsStore or 
ScheduledCommandStore depending on the yielded message type
- it notifies the event handlers using EventDispatcher
- it discards the aggregate

The aggregate should not inherit from anything and nothing should be 
injected into it. It should remain pure, side effect free. Any side effect 
should be observed by its yielded events.

I like this style because it reduces a lot of code duplication found in the 
other style (command handler being in the Application layer) where almost 
every command handler looks the same: it loads the Events from the store 
using a Repository, it factories a new Aggregate, it rehydrates the 
Aggregate (by applying the events to the Aggregate), it calls a method on 
the aggregate, it collects the events, it persists the events and then 
notify all subscribers (event handlers). In cqrs.nu's style this entire 
algorithm can be extracted in a CommandDispatcher.

So, I propose (at least) the following interfaces (in the namespace Cqrs)

//events

interface Event;


interface EventDispatcher;


interface EventSubscriber;


interface MetadataFactory;


interface EventStore;


interface AggregateEventStream extends EventStream;


interface EventStream extends \IteratorAggregate;


interface EventStreamGroupedByCommit extends EventStream;


//commands


interface Command;


interface CommandDispatcher; //can be decorated by a 
CommandDispatcherWithCommandValidation


interface CommandSubscriber;


interface MetadataWrapper;


interface CommandValidatorSubscriber; //used by 
CommandDispatcherWithCommandValidation


//scheduling


interface FutureEventsStore


interface ScheduledCommand extends Command, ScheduledMessage;


interface ScheduledEvent extends ScheduledMessage


interface ScheduledMessage extends IdentifiedMessage;


interface IdentifiedMessage;


interface CommandScheduler;


interface ScheduledCommandStore;


//read models and sagas (process managers)


interface ReadModelInterface;


interface SagaEventTrackerRepository;



I know that there are a lot of interfaces, but in fact, in a working 
application, more interfaces are needed. 

In order for this to work, the minimal requirements from the code in the 
Domain layer is the Command interface (for its getAggregateId method). The 
Event interface should be used only to detect event handlers by reflection. 
So, the domain code remains (almost) pure.

I have a todo <https://github.com/xprt64/todosample-cqrs-es> example on 
github if you want to learn more.

I know that my question mixes the proposed standard with my implementation 
but I don't know how to start the discussion otherwise.

So, what do you think?

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to php-fig+unsubscr...@googlegroups.com.
To post to this group, send email to php-fig@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/0c9a062b-4f1b-4f3c-85d3-433a93fdb234%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to