Reputation: 5494
I am trying to model a scheduling application for my company and could use some suggestions. I'd like to follow a domain-driven design, if appropriate.
The domain consists of a Show object which represents one trade show, exhibition or conference where we may be promoting our products. It has start and end dates and times, an agenda, list of speakers, location, etc. Quite a bit of work can be done with the Show, such as assigning speakers, registering attendees, cancelling, etc.
We typically participate in a Show as part of one or more marketing Campaigns. A Campaign also has start and end dates and other information as well as a list of Shows we will be attending for that Campaign. It is possible that we will be promoting more than one Campaign at a given Show.
Shows can be added or removed from Campaigns and when a Show is cancelled, it must be removed from any Campaigns it was associated with.
My first thought was to have a Schedule aggregate root with a list of Campaign entities that contained a list of Show objects. But I need a way to access stand-alone Shows - and a Show can be associated with more than one Campaign.
Looking at my use cases, I am developing a Silverlight client (but may also go mobile). The main view will be a calendar-type UI (like Outlook) that displays each Show as an appointment. There are also side bars that display Upcoming Shows, Current Campaigns and Shows that have follow-up tasks. When I double-click an item in any of these views, the Show details are displayed in a child window.
Any suggestions how to model this domain in my application code?
Upvotes: 3
Views: 2614
Reputation: 47627
But I need a way to access stand-alone Shows - and a Show can be associated with more than one Campaign.
Instead of trying to put everything underneath Schedule aggregate root (term that does not appear in your language when you talk about domain freely), try having 2 aggregate roots - Show and Campaign.
A Campaign also has start and end dates and other information as well as a list of Shows we will be attending for that Campaign.
It might be unnecessary for Campaign to hold reference to Show. If show knows Campaigns it promotes, that is enough to find it when you will be displaying Campaign information.
Shows can be added or removed from Campaigns and when a Show is cancelled, it must be removed from any Campaigns it was associated with.
No, it should not.
Show should be marked as canceled and campaigns would just hide it if necessary.
I would start with something like this.
It was only due to my attempt to be concise that Schedule was not introduced until I started discussing the model. In fact, the Schedule is the whole point of the app. The Schedule represents all of the Shows.
Quite likely there are requirement that asks for introduction of Schedule in Your domain model. But since I didn't hear it yet (or didn't understand Your domain good enough), I would just name my application as Scheduler. Or Scheduler bounded context, if application is more than about scheduling shows and campaigns.
Also, in the customers' minds the Show doesn't necessarily know about the Campaigns. In all of our discussions, they only ever referred to assigning Shows to Campaigns.
If Show must exist in "stand-alone version", it's an aggregate root (pushing it down under Schedule would not change a thing, that would just add one more abstraction layer. Show would still be independent from Campaigns). If there is need to figure out Campaign/s Show is associated with while being seen as in "stand-alone version", there should be an association Show->Campaigns. Despite that it might feel a bit contradictory to domain, you can look at that as a sacrifice.
We trade ability to express ourselves with clearness of original idea (Uncertainty principle can be used as a great analogy here). After all - we can't capture mental models completely and thoroughly anyway.
Logically I agree with your point but I would also want to ensure that there was only ever one instance of the Campaign shared by all Shows that has been assigned to it.
You should focus a bit on life cycle of domain objects.
There is a huge difference between construction and reconstruction of an object. Typically, Campaign would be constructed once only, after that - it would be only reconstructed from data store. If you ensure that different instances of same Campaign (from domain perspective) can't be saved twice - usually that's enough.
This is what led me to my original thought that Campaign was the root but doing so ignores the reality that there will be Shows that are not part of a Campaign.
Yap... You are right on this.
Upvotes: 4