The inquiry arrived: “Are time lapsed events Domain Events?” The question is the result of wrestling with whether YearEnded and similar occurrences are actually useful. The inquirer’s assertion is that rather than capturing the fact that the year ended, just send a Command that requires some outcome as a result of the fact that the year ended.
Of course you may choose to send a Command to have something done as a result of reaching a time threshold. It may be neither right nor wrong to do so. Yet, if you are trying to use Domain-Driven Design you would be better off by asking the business. In other words, it’s not your opinion or mine that matters. It’s how the business thinks about the time threshold being reached and what should be done in reaction to that.
I get the impression that many think that a Domain Event is limited to use with Aggregate modification or mutation; that is, only when the Domain Event describes a state change to a given Entity or Aggregate. While this is certainly where we mostly think of a Domain Event being used, it need not be limited to such.
For example, a Domain Event can be used to capture the fact that some time threshold has been reached, even if you don’t want to apply it to an Aggregate. You may think that time is not a part of your domain. Not true. Time happens in every domain and that’s why even a Domain Event that captures a mutation to an Aggregate generally retains the date-time of a change to the model. Thus, an elapsed time that the business cares about has happened in the domain. Time happens everywhere.
I am not saying that you will necessarily apply a time-based event to some Aggregate. Sure, you might need to record TenureAchieved—a time-based event—for an Employee. That’s not my point, but rather that you don’t need to limit Domain Events to be used only in relation to Aggregate mutation. A Domain Event can happen for other reasons. “It Happened” doesn’t always mean “It Mutated.”
When using DDD an important question about anything in the software is,
Is it important to the business, and if so, how should the important business concern be modeled?
If there is any reason for a Command to be sent in reaction to some time threshold being reached, what happened is important to the business. If it is not, then the question holds little weight because developers are possibly inventing something. Maybe that “something” is useful or possibly just interesting to the developers, but it’s not based on an actual DDD mindset where the business is involved in modeling this solution.
In my estimation any past occurrence that is of interest to the business is worth capturing as a Domain Event. If you just send a Command that is not produced as the result of a Domain Event, the question is, what caused the Command? For example, if it was not a user who submitted the Command then what is the reason for sending the Command at all? Having a Domain Event that models a time sensitive occurrence provides the reason and explicit traceability.
A second question is,
If it’s important enough to be modeled then what is the Ubiquitous Language of this model?
This requires engagement with at least one business expert. When discussing this modeling concern, do business stakeholders talk about the time threshold explicitly or only about what needs to happen as a result?
Given that they have a name for the time threshold then it may be more explicit than “year ended.” For example, it could well be FiscalYearEnded or MarketClosed or something else specifically relevant to the business. That’s important knowledge to enter your Ubiquitous Language.
Lacking a name doesn’t mean that it’s not important. It’s your job to ask the right questions to uncover a name, and you may just discover a missing concept.
Failing the previous two tests, it seems unlikely that using a Domain Event to capture the time threshold is necessary. Perhaps your team will decide to model a Domain Event for this anyway. If you do model it make sure you have business consensus on the new name to enter your Ubiquitous Language.
Still, there is the possibility that reason for and traceability of the cause of some time-based Command is unimportant to the business. If only what must be done as a result of reaching the time threshold is significant, it sounds to me more like an intermittently run cron job. In this case the Ubiquitous Language will include the name of the job/task and its properties and behaviors. The name of the job/task is significant because it’s required by the business and they discuss it with the team. The properties of the job/task will likely include the one or more time thresholds that cause one or more Commands. The behaviors will include the creation of one or more Commands and how they are sent.
Even if the job/task seems to be important while the time threshold isn’t, I think caution is in order with this kind of approach. You may already know of multiple operations that must be carried out as a result of some elapsed time being reached, or you will discover others sooner or later. Quoting the previous paragraph, “time thresholds that cause one or more Commands,” strongly suggests how common this is. If this is so in your model, consider the creation of a Domain Event that will trigger the multiple operations, because triggering multiple operations means the time threshold itself is quite likely significant to the business. Again, it’s your responsibility to call out this significance and seek a name for it.
In summary, being resistant to the use of Domain Events for triggering time-sensitive operations may be justifiable in some cases but possibly not in most cases. Also, as developers it’s not our call, but is a decision that should involve the business.