Designing Good Commands

Designing Good Commands

Working with an event-driven architecture, I got stuck wondering how best to structure my Commands, and would love to steal your ideas hear what you think.

In this web-app, very much like Pintrest, users create and manage “Galleries” of “GalleryItems”.

A “GalleryItem” is just an image with a title, description, and tags. Users can reorder the items.  Multiple users can collaborate on a single gallery.

How would you structure an UpdateGalleryItems command?  Take a second to think of what approach you would take, to not be swayed by my jibba jabba.

Mr T says "Think for yourself"

The simplest would be for the update command to include the entire new state of the Gallery.

class UpdateItemsCommand extends BaseEvent {
    public final newState: Gallery;

However, in most cases that would include a lot of excessive data, and would make it impossible for two users to edit a gallery simultaneously (as the second user’s update would clobber over the first’s).

What we really need is some way to express what has changed. I thought of 3 ways to do this.


1. One approach would be to use a new Type nearly identical to GalleryItem, but with all the fields nullable.

class UpdateItemsCommand extends BaseEvent {
   public final updatedItems: Array<GalleryItemUpdate>;

...

class GalleryItemUpdate {
    public var url:         Url;
    public var comment:     Null<String>;
    public var tags:        Null<Array<Tag>>;
    public var newPosition: Null<UInt>;
    public var deleted:     Null<Bool>;

We would need extra fields to capture reordering, and for deletions. 


2. Alternatively, we could express the various types of changes with only the data needed for them:  items deleted, added, mutated, and moved.

class UpdateItemsCommand extends BaseEvent {
   public final itemsDeleted: Array<Url>;
   public final itemsAdded:   Array<GalleryItem>;
   public final itemsMutated: Array<GalleryItem>;
   public final itemsMoved:   Array<Tuple<Url,UInt>>;

3. Yet another: we could effectively create a git-commit, by converting the Gallery’s old state and new state to JSON, and then diffing that text.

Take another second to think about your own approach, and the pros and cons of each?

Winnie the Poo Thinking

First I eliminated the git-commit approach. While “clever”, is not very performant as it requires serializing and deserializing the entire Gallery even if a user is only adding a single item (the most common use-case).  Also, while it may seem to be robust, since we could updated the definition of the GalleryItem without needing to change the Command, we actually lose the intent of the user’s changes, so it would be impossible painful to apply Update Commands created from GalleryItem.v1 to GalleryItem.v2

I wanted to optimize for minimal event size (minimize i/o) and for clarity in the code. Both remaining approaches seem about the same size, but approach #1 seemed a little more clear due to the changes for any item being cohesive, rather than split across (for example) itemsMutated and itemsMoved.


Now it’s your turn! Did you think of a better approach? Would you like to see more of this type of comment? Leave a comment or reach out to @scottPlusPlus to help me level up my coding.

ScottPlusPlus

Working to upgrade our democracy by making voting more awesome (ex: STAR Voting). Reach out if you want to chat about saving the world.

Leave a Reply

Your email address will not be published. Required fields are marked *