public class AddTimeRangeCommand {
public final UUID timeProgramId;
public final LocalTime startTime;
public final LocalTime endTime;
public final String value;
public AddTimeRangeCommand(UUID timeProgramId, LocalTime startTime, LocalTime endTime, String value) {
this.timeProgramId = timeProgramId;
this.startTime = startTime;
this.endTime = endTime;
this.value = value;
}
}
00:00 Off 23:59
|----------------------------------------------------------------------|
00:00 Off 08:00 On 12:00 Off 23:59
|------------------|------------|------------------------------------|
To simplify this I'd only use the first, temporal way; this is Event Sourcing. The current state of the time program is then caused by the original issued AddTimeRangeCommands, resulting one-on-one in a stream of TimeRangeAddedEvents. The current state in your example is then a result of applying two TimeRangeAddedEvents: [0:00-23:59]-off and [8:00-12:00]-on. Applying this eventstream reconstitutes your state. You can make a projection of this stream to easily query the current state. No other events are necessary to get the current state.
In short: state is the result of events. The stream of events completely constitutes the (current) state. The current state is not something extra besides the stream of events.
Have you reviewed this talk by Greg?
https://skillsmatter.com/skillscasts/5437-answering-a-question#video
In what you describe, you use TimeRanges in two different ways:
- the TimeRange that is added to the previous stream of TimeRanges.
- the TimeRanges in your "internal model" that describe the current state of your time program.
To simplify this I'd only use the first, temporal way; this is Event Sourcing. The current state of the time program is then caused by the original issued AddTimeRangeCommands, resulting one-on-one in a stream of TimeRangeAddedEvents. The current state in your example is then a result of applying two TimeRangeAddedEvents: [0:00-23:59]-off and [8:00-12:00]-on. Applying this eventstream reconstitutes your state. You can make a projection of this stream to easily query the current state. No other events are necessary to get the current state.
In short: state is the result of events. The stream of events completely constitutes the (current) state. The current state is not something extra besides the stream of events.
Ok, here is what I understood from your hints. An Aggregate can have a model that manifests through the stored (and replayed) events. To build the model, functions can be used that sometimes can be complex. Like this could be in in my representation of the time ranges. This state is kind of a projection from the events. As already some persons within this forum pointed out you can call this the internal (read) model. This is solely used to validate incoming commands and ensure the business rules (invariants).