Luca Masera
Luca Masera

Reputation: 732

Extra boundary data in command execution

I've a design problem that is turning around in my mind since a while and I'm not finding a good solution about it. It's about CQRS and domain boundaries.

Let's say I've a context, that's about taking bookings, and consequently events, for a system. The system allows to have a single booking linked to single event (that's already done, no problems), and weekly bookings linked to a collection of events. Weekly bookings are done defining a day of the week (extra data is not relevant); a weekly booking has always a starting and ending day (half year).

The system has also two types of days: normal days and not working days, where an event cannot be held.

As a business request the users want that for every weekly booking the system alone cancels that particular events that are hold on not working days.

Actually bookings and events are stored in two tables. An event is canceled when it's stored with a special flag. I've no link with the table of the days because I've never used it in my business context. As business boundary (with other small data, not relevant here) this was working great, up to now.

Here is my problem: to satisfy the users request (create an event for every deleted day), I need informations about all the days of half year (just the ones in the same weekday are enough). But, to obtain this information, how can I proceed?

My possible solutions:

  1. Load all the days of half year in the root entity. This could be really heavy, and I've to extend my business boundary.
  2. Preprocess the command, creating one with extra informations. It would be a command in command, something I've read being dangerous. That's enough for me.
  3. Extend the command with the list of invalid days. How I check that a day is invalid? I've to access data outside my actual boundary, that's the same as 1.
  4. Create a service that is used in the command handler to get the list of the not working days. The days context information would be moved in a common (or shared) context.
  5. Create an event listener for weekly events. When a weekly event is created, it loads the list of not working days (for that weekday of that half year) and fires a sequence of commands to cancel that particular days. This would seal the boundaries, not adding extra data to a common context and reuse same code (cancel event) for extra purposes.

Which would be the best solution?

Upvotes: 0

Views: 57

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57239

Litmus test : ask your stakeholders if it ever happens that a working day becomes a non-working day, and what is supposed to happen to weekly bookings on those days. Also, does it ever happen that a non-working day becomes a working day, and what is supposed to happen to bookings on those days.

Create an event listener for weekly events. When a weekly event is created, it loads the list of not working days (for that weekday of that half year) and fires a sequence of commands to cancel that particular days. This would seal the boundaries, not adding extra data to a common context and reuse same code (cancel event) for extra purposes.

Close, based on my understanding of what you have written.

To my mind, you really have two different aggregates; you have the definition of the weekly booking, and you have daily schedules which collect events from different bookings.

When you create a booking, your inputs are a start date, and end date, a day of the week, and probably a domain service that can return a list of days of the week in that range. Think schedule or itinerary -- we're defining the candidate days for this particular booking.

You event listener, upon seeing a new booking, fires a command to the schedule aggregate for that particular day, adding the event requested by the daily booking. Because the schedule knows whether or not it is a "non-working day", it can mark each of those events as scheduled or cancelled (if you want that information to be explicit; you could leave it implied by the state of the working day in some systems).

Empty schedules can be created in advance, or on demand using some generic recipe to determine whether or not they are working days, and can support changes to their own working status if that's part of your current domain.

The key ideas here are that non-working days are a part of your domain model, and since they span multiple booking objects, they clearly are an entity that sits outside of the booking aggregate.

Upvotes: 1

Related Questions