I'm in the process of writing a little application using CQRS to play with the concepts and learn it. I'm not using event sourcing as I want to start slow and grasp what this is all about.
I've written my domain model and put a great deal of effort to try and make all of my members private so to push myself to think about behaviors rather than public properties (tell don't ask stuff). I listed some behaviors associated with that model and I've also written the command used to "trigger" that behavior.
I have a command named "CreateScheduleCommand" which not so surprisingly creates a schedule. Now in an event sourced world something would, at the end of the command, gather all the chances and publish them to who ever is listening, and I assume someone's job would be to update the read model associated with the affected domain model. But now, not using event sourcing and not having public properties, I can't access the changed properties of the domain model being updated or created, to update the read model. My command returns void so what I did was that the command dispatcher calls "Handle" on the handler and passes a continuation, and that continuation is an action taking the processed domain model as a parameter so that the dispatcher can play with it after the command has finished doing his business. What I had in mind was that the dispatcher could then "resolve" a "IDenormalizer<TCommand>" which would know what to do to update the read model of the domain model being modified.
So I guess my question is:
- Is this a good idea? (if not, how to update the read model in a non-event-source world?)
- Would it be a good idea to put my fields public so that the denormalizer can see them? (I had also thought about passing a DTO instead of the real domain object in the continuation, but then again, how to iniutialize the DTO if all the fields are private?)
here is a little bit of code some people know what I'm talking about:
public void Dispatch<T>(T command) where T : ICommand
{
// TODO wrap within transaction
// TODO add a OnError callback
var handler = _container.Resolve<ICommandHandler<T>>();
try
{
handler.Handle(command, new Just<Action<object>>(o =>
{
// do stuff, get denormalizer for object and update read model
}));
}
catch (Exception ex)
{
// TODO do stuff
}
}
public void Handle(CreateScheduleCommand command, Maybe<Action<object>> continuation)
{
// inserting in persistence store
continuation.Do<Action<object>>(c =>
{
//var schedule = new Schedule(command.Name, command.StartDateTime, command.EndDateTime);
c(new ScheduleDto()
{
Id = id,
Name = command.Name,
StartTime = command.StartDateTime,
EndTime = command.EndDateTime
});
});
}
I'm also populating the DTO from the command itself and I don't really like that idea... but since all my fields are private...