1

I'm currently developing an application using reactive programming. Every entity creation or modification in the system publishes an event and no two entities can be created/modified within the same use case.

In this situation, there are entities that have to be created based on specific states of other entities. For example, there is an entity Slot that, when created with a state IN_AUCTION, should trigger the creation of an Auction entity. This is optional, as the Slot could be created with a state AVAILABLE, in which case, no Auction should be created.

Given this is the case, my doubt is about the type of event to publish when the Slot is created. These are the options I've thought about:

  1. Publish a generic SlotCreatedEvent. In this case, the listener would need to verify the state of the Slot, either by adding it to the Slot event or by querying it to check its state.
  2. Publish a SlotInAuctionEvent or a SlotAvailableEvent. In this case, there would be a specific listener that would create the Auction without checking the Slot state but if I follow this approach I could have an explosion of events.

So, given this example, what's the expected granularity when publishing events? Should there be a specific event for each state/entity modification or just a generic one with all the information of the entity modified?

13
  • 3. Publish a SlotInAuctionEvent that only creates an auction if the required conditions exist? – Robert Harvey Feb 8 '18 at 18:01
  • @RobertHarvey I think the SlotInAuctionEvent indicates that the condition has been met. The question is if it is a good idea to have a separate event for every state in which a slot can be created vs. having one event that provides the data for the listeners to do the condition-checking. – doubleYou Feb 8 '18 at 18:15
  • Can a slot later change its state to IN_AUCTION and will that also trigger the creation of an auction? – doubleYou Feb 8 '18 at 18:16
  • @doubleYou: If you only create the slot and fire the event when conditions are correct, you won't have to do the check afterwards. Hell, you might not even need the event. – Robert Harvey Feb 8 '18 at 18:26
  • @RobertHarvey so the SlotFactory checks the condition and then triggers (via event or otherwise) the creation of an auction? I think that's basically option 2 in that you need a separate event for each condition. Or did I misunderstand? – doubleYou Feb 8 '18 at 18:44
1

In principle, I think what's most convenient for your event handlers should be a secondary concern. One of the major advantages of events is that the event source does not need to know anything about the consumers - so you don't know what their needs are.

The question really comes down to what constitutes an event conceptually. I would argue that creating an "in auction" slot and a "not in auction" slot are not separate events - otherwise, you end up with a separate event for every combination of parameters.

However, you'll also want to avoid flooding your consumers with unnecessary information. Furthermore, I think it's wise to avoid sending the same information in different events, if possible.

In your example, you risk duplicating the status information in the SlotCreated event and the SlotStatusUpdated event. If you had to react to a slot being 'available', you'd have to subscribe to two events.

A possible solution to this problem might be to publish two events when you create a slot: the SlotCreated event does not carry slot-status information, but you'll also immediately raise SlotStatusUpdated. Then AuctionCreator only has to subscribe to the latter. (If SlotCreated is of no interest to anyone, you could even skip this event).

Side Note: A module that only needs to react to new slots with a given status will have to do more work in this case. I'd argue that this is a natural reflection of the more complex condition. (If there are many such subscribers, you could have an intermediary that combines both events to a new event). In any case, there may be situations where this approach is not practical, but I do think it would usually be a relatively clean solution.

I think we can summarize the above considerations into the following rules of thumb:

  • If two events hold the same information, extract that into a new event

  • Don't create a new event just to suit a subscriber's needs

Unfortunately, this still leaves one question open: do we have a StatusChanged event or separate SlotOpenedForAuction, SlotReserved and SlotMadeAvailable events?

There might be a technical reason for choosing separate events: if you have a large number of subscribers, each of which only has to handle slots in a particular status, separate events are more efficient. (Raising an event is an O(n) operation). Otherwise, you should use the domain terminology as a guide - i.e. do users talk about a slot's 'status'?

6
  • As of now there aren't many use cases really. There is only the handler that schedules the next slot and the one that creates the auction. My concern is about the information to include in the events, if that is a symptom of a design problem.But thinking about it, maybe what I'm missing is a middle step.An auction also requires an end time which is based on a configuration stored on the entity that triggers the slot creation in the first place. So I think I can publish the event,listen to it in the module with the config and publish a CreateAuctionCommand.Would that make sense? – Kilian Feb 8 '18 at 23:13
  • Is the EndTime a property of the Slot (conceptually speaking)? If so, I'd include it in an event. Otherwise, I'm not sure if the SlotCreator should be concerned with auctions (and their end times) at all - is there a reason the AuctionCreator can't hold that configuration? In your suggestion, it seems the SlotCreator is responsible for creating both Slots and Auctions. – doubleYou Feb 9 '18 at 16:58
  • The Slot has an end time of its own. The Auction end time is defined in the configuration of the Room entity, that is who triggers the Slot creation in the first place. That's why I suggested listening to the SlotCreatedEvent so the Room can react to it by triggering the CreateAuctionCommand that would include the slotId and the Auction configuration. – Kilian Feb 9 '18 at 18:24
  • Okay so (correct me if I'm wrong): SlotCreator creates a event with an expiration time (which should be part of the event). In response to that event, AuctionCreator creates an auction with its own end time, based on some config that AuctionCreator holds, and possibly the expiration time of the SlotCreatedEvent. So far so good. Now SlotCreator and AuctionCreator are actually both implemented in Room. That may be totally fine, or it may put completely separate responsibilities into Room - I can't decide that without knowing the rest of the system. – doubleYou Feb 9 '18 at 18:38
  • Room, Slot and Auction are all completely separated. Each one only publishes events of itself and there are listeners reacting to them. Each listener calls a use case that contains references to components that handle each type of entity. In terms of DDD, currently each one is its own aggregate and I haven't found a reason to include any within another one. Use cases would be the domain services. Room contains config for each Slot and the Auction associated so, for me, a use case should call Room for each event published by Slot and Auction and let it decide next action – Kilian Feb 11 '18 at 14:12

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.