3

I'm new to eventsourced apps and since the beginning I'm facing an issue that I'm unsure how to resolve.

I work in ecommerce and I always try to convey meaningful events to my aggregates like PriceIncreasedEvent, ProductDeactivatedEvent, OutOfStockEvent etc

But many times I just want to do a simple "CRUD" style with my aggregate. For instance, the user can change the product image, but I don't want to mess with my aggregate with ImageUploadedEvent event, since it isn't part of the domain its supposed to handle.

All I want to do is simply set the new image path in the database. But since "projections" are supposed to be disposable, I can't do that, because I would loose information.

This often happens with other types of editorial data, like the title/name of something. I don't want to create a event TitleChanged, I know that's a code smell, it doesn't matter for the domain that the TitleChanged. I just want to change it.

Maybe eventsourcing was a bad idea? How do you guys handle these kind of scenarios?

  • How is TitleChanged not an event in your domain? – RubberDuck May 29 '18 at 9:27
  • 2
    If "it doesn't matter for the domain", why do you want to change it? – Caleth May 29 '18 at 9:43
  • What I meant is it doesn't make sense for me to "event source" some kinds of domain interactions. – lucaswxp May 29 '18 at 14:06
  • Although those minor events don't seem interesting at first, it is part of the recorded history if your E-commerce app. They just as well could not be relevant (now), but might become so in the future. Additionally, you loose a lot of the benefits a thorough event sourced system has if you do emit events for some actions, but not for all. – Steven May 30 '18 at 6:58
2

You don't need events at all unless you need the benefits that an event provides.

Here are the benefits that an event provides:

  1. Asynchronous notification
  2. Decoupling
  3. Well-suited for applications or tools whose control flow is based, not on its structure, but rather on internal or external events (especially GUIs).
  4. Fundamental architecture for message queues.

In addition, event sourcing (potentially) provides:

  1. Rebuild state
  2. Temporal queries
  3. Event replay

Do you need those things (for a given element in your architecture)? If you don't, then you don't need an event (for that particular element).

Further Reading
Event Sourcing (Fowler)

  • Yes, many parts of the domain do need them. I'm unsure how to integrate the parts that don't need them. – lucaswxp May 29 '18 at 15:51
  • The old fashioned way. I'm pretty sure that Event Sourcing doesn't mean everything in your application has to be an event. You should also read martinfowler.com/eaaDev/EventSourcing.html – Robert Harvey May 29 '18 at 15:53
  • The problem I'm facing is with projections. "The old fashioned way" I would just update the database, but since a projection is supposed to be disposable, I'm thinking in using another collection for this. – lucaswxp May 29 '18 at 16:29
1

It seems that you have two domains.

One domain is e.g. product data. It is event-sourced because you care about what @robert-harvey mentions.

Another domain is something more fleeting, for which you don't care about the history, replication, auditing, etc, but you still want to persist the latest state. If you have such a domain, it effectively caches a projection form the event-sourced domain; if it's there, it uses it, if not, it should trigger its recalculation and wait for it to complete.

Chances are that in your particular case you still have a single domain. If I ran a store (and I have), I would be deeply concerned with the history of changes of product images, and its relation to price and description changes. So ProductImageUploadedEvent likely belongs to the event-sourced domain, and should contain enough metainfo to find out which image it was.

  • "if it's there, it uses it, if not, it should trigger its recalculation and wait for it to complete" That's a good point. Thanks for sharing. About "be deeply concerned with the history of changes of product images", I do get your point, but it's something I just don't see being relevant in the business for a long time. – lucaswxp May 29 '18 at 20:47
1

I feel you're not distinguishing the difference between an Event Driven Architecture and Event Sourcing. In an EDA events are created by some event source (UI, API, or internal to the app) and acted upon by the event processor, often resulting in a change to an Aggregate Root. These event can or cannot be persisted depending on their significance. This type of event seems to be what you’re talking about when a user updates their image, and the event may be ImageUpdateRequestedEvent.

Event Sourcing is when ALL state changes are persisted so the current state of an Aggregate can be determined solely by the recorded events. Imagine if you had a server with unlimited memory, guaranteed not to fail, and unlimited processing power. In this case you wouldn’t bother persisting data to a database. You would keep all events in memory that affected a certain aggregate and merge them all to get the current state. In this case, if you didn’t save that image change event, the update to the aggregate would be lost.

This is what they mean whey they say “projections are disposable”. They are disposable because you have saved off all actions that affect the state of the data, either in a DB (since we’re not in that perfect computing world yet) or in an event.

See Martin Fowler where he says (emphasis mine) “The fundamental idea of Event Sourcing is that of ensuring every change to the state of an application is captured in an event object, and that these event objects are themselves stored in the sequence they were applied for the same lifetime as the application state itself.”

If you truly are doing Event Sourcing, you must save the image update event. If you are really doing Event Driven Architecture where you save some events because they could be useful in the future, then you can just update the DB and lose the image update event without repercussions.

0

Hmmmm I think you may have conflated your EventSource events and your domain events, although its not 100% clear.

say I have an object: (excuse the rough and ready event sourcing approach)

Item
{
    Price {
        get: { return _price;}
        set: { 
            eventSourceEvents.Add(new EditEvent("price",value)); //generic eventsource event
            if(_price > value) { this.isDiscount = true; }  //domain event
            _price = value;}
        }
}

Now when I set the price the audit Domain 'event' fires (I've slimmed it down from an event handler, or mediator or whatever for the example) AND the event sourcing event is stored

But this isn't my EventSource event

EventSourceRepo 
{
    SaveItem(Item item)
    {
        foreach(Event in item.eventSourceEvents) { //store the event};
    }

    GetItem(string id)
    {
        Item i = new Item();
        foreach(var e in db.GetEventsForId(id))
        {
            //playback events
            if(e.key == "price") { i.Price = e.value;}
        }
    }
}
  • Hey @Ewan, I dont get it "you may have conflated your EventSource events and your domain events". What is a "generic event"? Where the "domain event" in your example? You merely set isDiscount = true, you dont persist those? – lucaswxp May 29 '18 at 14:10
  • you persist the event-source events. ie every change that isn't generated internally. The domain events are fired in response to those changes and not persisted, but may be (optionally) re-fired when you rebuild the object from the event-source events – Ewan May 29 '18 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.