CQRS How to avoid repeating fields between command and event?

Viewed 1100

I'm implementing a project using CQRS and Event Sourcing. I realized that my commands and my events are nearly always the same.

Let's say I have a command CreatePost :

public class CreatePost implements Command {
    private final String title;
    private final String content;
}

The event fired from this command is the same :

public class PostCreated implements Event {
    private final String title;
    private final String content;
}

How do you handle that in your applications ?

EDIT : Of course I'm aware of basic OOP technics. I could create an abstraction having the common fields, but this question needs to be taken in the CQRS/ES context.

6 Answers

I've run into this, and almost universally I've not found a case where the event needed different properties than the command for a particular domain action. I definitely find the menial copy/paste duplication of property getters/equals/hashCode/toString pretty annoying. If I could go back, I'd define a marker interface Action and then

interface Command<T extends Action> {
  T getAction();
  // other properties common to commands of all action types...
}

class AbstractCommand<T extends Action> implements Command<T> {
  public T getAction() { ... }
  // other properties...
}

interface Event<T extends Action> {
  T getAction();
  // other properties common to events of all action types...
}

class AbstractEvent<T extends Action> implements Event<T> {
  public T getAction() { ... }
  // other properties...
}

Then for each domain action, define concrete implementations.

class ConcreteAction implements Action {
  // properties COMMON to the command and event(s)...
}

class ConcreteCommand extends AbstractCommand<ConcreteAction> { ... }

class ConcreteEvent extends AbstractEvent<ConcreteAction> { ... }

If the command and event action properties need to diverge for some reason, I'd put just those particular properties in the ConcreteCommand or ConcreteEvent classes.

The inheritance model here is very simple. You may only rarely need to do anything more than extend the abstract classes with nothing more to implement than the common Action. And in the case where there are no properties needed for the Action, just define a class EmptyAction implements Action implementation to use in those types of commands and events.

Related