1

This question is more of a general question about how to model simple one-to-many relations using collections: should a change in a list item be reflected in the version of the aggregate containing it?

The domain is about meeting scheduling (like in Outlook). I have a Meeting entity, which can have multiple Participants. A participant can accept/decline meeting requests. Rescheduling a meeting nullifies all of the participants confirmations.

I thought of two ways to model this.

Option 1 The Meeting aggregate will contain a list of Participants where each Participant has a ParticipantId and a Status (accepted/denied). The problem here is that every Accept or Deny command, for a specific participant, increments the Meeting's version, which means two participants will enter a race condition if trying to Accept the meeting request based on the same original version. Although this could be solved by re-reading the Meeting's document and retrying the Accept command, it's quite annoying considering how often this could happen. Another approach is to ignore the meeting's version when executing the Accept command, but this introduces a new problem: what happens if, after sending the meeting requests, the meeting has been rescheduled? In this case we can't afford to ignore the Meeting's version, because this time the version DOES represent a real version that should be considered. BTW, is it at all a good practice to ignore the version in some of the commands and not in others?

Option 2 Extract a Participation aggregate out of Meeting. Participation will have MeetingId, ParticipantId, and Status. It will also have its own version. This way, when participant X Accepts the meeting request, only the relevant Participation will be modified, and the rest will be left intact. And, when rescheduling the meeting, a "Meeting Rescheduled" event will be published and an event handler will respond to it by resetting all of the Participations' statuses to "NotAccepted" regardless of their current version. On the one hand this sounds logical in the sense that a meeting's version shouldn't be incremented just because someone accepted/denied its request. On the other hand, modeling Participation as a standalone aggregate doesn't sound quite right to me, because it is has no meaning outside of the context of the meeting.

Anyway, would love to get feedback on this and see the various approaches to this problem.

1
  • 4
    Why do you complicate things with that version? I like Option 1 but without the version. When the Meeting is rescheduled you simply remove/invalidate all the confirmations (a confirmation is a nested entity). Aug 22 '17 at 7:16
2

I don't think this problem is restricted to DDD, sounds more like a general modeling problem, but anyway.

Option 2 is not bad, and it makes the "mental model" you already have explicit: a change of the participation state does count as a change of the meeting, simply because it is not part of the entity. However, if you are looking for a more simple solution, use "Option 3": try to avoid the usage of the version attribute at all (and if you have one for technical reasons, ignore it for this use case).

When a meeting is rescheduled, why not create a new meeting entity, with a new meeting ID? Interpreting a rescheduled meeting as a different meeting (just with the same agenda and set of participants) is a perfectly valid point of view, and it will make sure you can correctly assign any meeting request answer to the correct meeting entity, independently from the order in which the answers are returned. For example, if a meeting was first scheduled at monday, and then rescheduled to tuesday, when someone acknowledges participation for the meeting at tuesday, and afterwards declines to participate at monday, you can easily deal with the answers, since you handle them simply as answers to different meetings - no version attribute required.

In case something different changes (like the agenda, or the set of invited people, or the location), you send a notification to the participants, but I assume you do not want change the state of their participation confirmations automatically. In case someone sends you another reply to the same meeting and changes his participation state - which any participant can do at any time, even when the meeting itself did not change - the latest answer counts.

Note for the case the meeting did not change a version attribute would not help you either to process multiple answers for the same meeting from the same participant. People might first acknowledge participation, and then retract their answer again, without the system sending them a new request, or without any change to the "meeting entity" in between. So you need something a "last answer counts" strategy either with or without a version number.

7
  • > why not create a new meeting entity Wouldn't creating a new meeting entity make it harder to track the meetings and associate them? It would, after all, be nice to see the old meeting as canceled in the UI instead of simply treating it as two distinct meetings. Aug 22 '17 at 15:31
  • Also, if a meeting becomes a new meeting because it now has a different date/time or location, shouldn't it be a VO? I'm really confused now :) Aug 22 '17 at 15:37
  • @AmirShitrit: I don't think this makes a big difference. The "new" (rescheduled) meeting will cause new invitations, and the old one gets deleted which causes canceling messages to all potential participants, so it will show up perfectly in the UI. Assume for a moment your program does not include a rescheduling feature, inviters can only create new meetings at a certain date & time, and if they want to reschedule, they need to cancel the old invitation and create a new one manually. I am pretty sure that would work fine in the real world.
    – Doc Brown
    Aug 22 '17 at 15:42
  • ... and now the rescheduling feature will be implemented on top of this: it just automates the process of copying the old agenda and set of participants to a new meeting entity, and bundled this with a canceling of the old in one step.
    – Doc Brown
    Aug 22 '17 at 15:44
  • @DocBrown for one of the primary use cases, you would probably need to store a cancellation reason for each meeting and, if the reason was something like "rescheduled" then also a pointer to the id of the rescheduled meeting so that users who go looking for the original meeting (say by clicking a link in an invitation email) can be directed to the rescheduled one. Aug 22 '17 at 17:01

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.